EntityFramework 6.x 학습 의 여러 상하 문 이전 실현 분포 식 사무 상세 설명

머리말
프로젝트 에서.NET Core 플랫폼 에 EntityFramework Core 를 사용 한 후부 터 EntityFramework 6.x 버 전 을 건 드 린 적 이 없다.현재 EntityFramework 6.x 는 가장 많이 사용 되 고 일자 리 를 찾 든 자신의 기술 을 향상 시 키 든 모두 자신의 수익 을 얻 었 다.또한 대부분의 시간 은 일 을 제외 하고EntityFramework 6.x 와 EntityFramework Core 의 책 을 쓰 는 데 시간 이 조금 남 았 기 때문에 EntityFramework 6.x 를 0 학년 부터 시작 하고 EntityFramework 6.x 는 많은 특성 을 추 가 했 기 때문에 시간 을 들 여 보고 정리 했다.이 절 은 자신 이 겪 지 못 한 문제 에 해당 한다.그래서 시간 이 좀 걸 렸 습 니 다.여러 개의 문맥 에서 서로 다른 데이터 베 이 스 를 옮 기 고 분포 식 사 무 를 실현 하 는 데 시간 이 걸 렸 습 니 다.기본 적 인 입구 로 서 책 과 동기 화 되 어 독자 들 이 공부 할 수 있 도록 하 는 것 도 제 작은 축적 입 니 다.글 에 오류 가 있 으 면 지적 해 주 십시오.
모델 구축
Entity Framework 6.x 내용 서술 을 시작 하기 전에 우 리 는 낡은 방식 입 니 다.먼저 모델 을 준비 합 니 다.우 리 는 예약 항공 편의 기본 모델 을 만 듭 니 다.하 나 는 항공 편 실체 이 고 다른 하 나 는 예약 실체 입 니 다.다음 과 같이 보 세 요.

/// <summary>
 ///   
 /// </summary>
 public class FlightBooking
 {
  /// <summary>
  ///   Id
  /// </summary>
  public int FlightId { get; set; }

  /// <summary>
  ///     
  /// </summary>
  public string FilghtName { get; set; }

  /// <summary>
  ///    
  /// </summary>
  public string Number { get; set; }

  /// <summary>
  ///     
  /// </summary>
  public DateTime TravellingDate { get; set; }
 }

/// <summary>
 ///   
 /// </summary>
 public class Reservation
 {
  /// <summary>
  ///   Id
  /// </summary>
  public int BookingId { get; set; }

  /// <summary>
  ///    
  /// </summary>
  public string Name { get; set; }

  /// <summary>
  ///     
  /// </summary>
  public DateTime BookingDate { get; set; } = DateTime.Now;
 }

public class TripReservation
 {
  public FlightBooking Filght { get; set; }
  public Reservation Hotel { get; set; }
 }
항공 편 과 예약 실 체 를 유지 하고 예약 항공 편 을 만 들 때 사용 합 니 다.EntityFramework 6.0+버 전에 코드 기반 설정(Code-based Configuration)이 나 타 났 습 니 다.데이터베이스 초기 화 전략 과 기타 등등 설정 에 대해 저 희 는 따로 설정 류 를 만들어 서 유지 합 니 다.예전 처럼 DbContext 컨 텍스트 파생 류 구조 함수 에 넣 지 않 아 도 됩 니 다.그러면 컨 텍스트 파생 류 는 깨끗 해 보 입 니 다.

public class HotelFlightConfiguration : DbConfiguration
 {
  public HotelFlightConfiguration()
  {   
   SetDatabaseInitializer(new DropCreateDatabaseIfModelChanges<HotelDBContext>());
   SetDatabaseInitializer(new DropCreateDatabaseIfModelChanges<FlightDBContext>());
  }
 }
다음은 두 개의 DbContext 상하 문 파생 클래스 인 HotelDbContext 와 FlightDbContext 를 설정 하고 정보 이용 특성 을 기본적으로 설정 하여 다음 과 같이 수식 합 니 다.

[DbConfigurationType(typeof(HotelFlightConfiguration))]
 public class FlightDBContext : DbContext
 {
  public FlightDBContext() : base("name=flightConnection")
  { }

  public DbSet<FlightBooking> FlightBookings { get; set; }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
   modelBuilder.Configurations.Add(new FlightBookingMap());
   base.OnModelCreating(modelBuilder);
  }
 }

[DbConfigurationType(typeof(HotelFlightConfiguration))]
 public class HotelDBContext: DbContext
 {
  public HotelDBContext():base("name=reservationConnction")
  { }

  public DbSet<Reservation> Reservations { get; set; }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
   modelBuilder.Configurations.Add(new ReservationMap());
   base.OnModelCreating(modelBuilder);
  }
 }
대응 하 는 맵 설정 은 이미 여러 번 서술 되 었 습 니 다.우 리 는 쓸데없는 말 을 하지 않 고 직접 드 립 니 다.

public class FlightBookingMap : EntityTypeConfiguration<FlightBooking>
 {
  public FlightBookingMap()
  {
   //table
   ToTable("FlightBookings");

   //key
   HasKey(k => k.FlightId);

   //property
   Property(p => p.FilghtName).HasMaxLength(50);
   Property(p => p.Number);
   Property(p => p.TravellingDate);
  }
 }

public class ReservationMap : EntityTypeConfiguration<Reservation>
 {
  public ReservationMap()
  {
   //table
   ToTable("Reservations");

   //key
   HasKey(k => k.BookingId);

   //property
   Property(p => p.BookingId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
   Property(p => p.Name).HasMaxLength(20);
   Property(p => p.BookingDate);
  }
 }
위의 두 컨 텍스트 와 같이 우 리 는 서로 다른 데이터 베이스 로 이전 할 것 이 므 로 연결 문자열 은 당연히 두 개 입 니 다.

<connectionStrings>
 <add name="reservationConnction" connectionString="Data Source=WANGPENG;Initial Catalog=ReservationDb;Integrated Security=true" providerName="System.Data.SqlClient" />
 <add name="flightConnection" connectionString="Data Source=WANGPENG;Initial Catalog=FlightDb;Integrated Security=true" providerName="System.Data.SqlClient" />
 </connectionStrings>
자,모델 과 문맥 이 모두 구축 되 었 습 니 다.그 다음 에 이전 으로 들 어가 보 세 요.아래 를 보 세 요.
다 중 문맥 이전
하나의 상하 문 을 옮 기 는 것 은 더 이상 할 말 이 없다.대부분의 장면 에서 하나의 응용 프로그램 에 하나의 상하 문 만 존재 하 는 것 같다.왜냐하면 배후 에 대응 하 는 데이터베이스 가 하나 밖 에 없 기 때문이다.이것 은 모두 가 손 쉽게 잡 을 수 있 는 것 이 고 여러 개의 상하 문 을 옮 기 는 것 은 서로 다른 데이터 베 이 스 를 옮 기 는 데 어떻게 해 야 하 는가?이전 명령 에 익숙 하 다 면 돌 이 켜 보 는 것 이 라 고 생각 하 세 요.그렇지 않 으 면 기본 적 인 참고 로 좀 지루 합 니 다.우 리 는 본문 에 들 어 갑 니 다.모델 을 데이터베이스 로 옮 기 고 지구 화 하려 면 다음 과 같은 세 단계 만 필요 합 니 다.
여러 컨 텍스트 를 다른 폴 더 디 렉 터 리 로 옮 깁 니 다.
Enable-Migrations 명령

추가 작업 명령

Update-database 명령

통합 프로그램 에 하나의 컨 텍스트 만 존재 할 때 저 희 는 Enabel-Migrations 만 있 으 면 됩 니 다.그러나 여러 컨 텍스트 가 존재 한다 면 컨 텍스트 를 명확 하 게 지정 하지 않 으 면 오류 가 발생 할 수 있 습 니 다.먼저 NuGet 콘 솔 에서 컨 텍스트 가 있 는 항목 으로 항목 을 바 꿉 니 다.

다음 에 Enable-Migrations 를 실행 하여 이전 디 렉 터 리 를 초기 화하 면 이전 이상 이 뚜렷하게 나타 납 니 다.

여러 개의 상하 문 이 존재 하기 때문에 우 리 는 어느 상하 문 을 이전 할 지 명확 하 게 지정 해 야 한다.명령 후 계속-contextTypeName 을 추가 하여 컨 텍스트 를 지정 하고-MigrtionsDirectory 를 이용 하여 이전 디 렉 터 리 를 지정 합 니 다.마지막 으로 다음 명령 입 니 다.(어떤 명령 이 있 는 지 모 르 시 겠 습 니까?명령 마다[-]바 를 추가 하고 Tab 키 를 누 르 면 원 하 는 명령 이 나타 납 니 다)Enable-Migrations -ContextTypeName FlightDbContext -MigrationsDirectory:FlightMigrations
그 다음 에 add-migration 명령 을 이용 하여 이미 걸 려 있 는 모델 에 대해 기본 프레임 을 바 꾸 었 습 니 다.즉,지난번 에 이전 한 후에 우 리 는 모델 에 대해 변경 을 했 습 니 다.이 를 다음 이전 으로 기본 프레임 을 만 들 었 습 니 다.이때 생 성 된 모델 상 태 는 걸 려 있 는 상태 또는 미 정 상태 라 고 합 니 다.FlightMigrations 디 렉 터 리 에 생 성 된 Configuration 클래스 를 이전 해 야 합 니 다.따라서 add-migration 명령 후-configuration TypeName 을 지정 한 다음-name 을 통 해 첫 번 째 기본 프레임 이름 을 지정 합 니 다.Add-Migration -ConfigurationTypeName EntityFrameworkTransactionScope.Data.FlightMigrations.Configuration -Name Initial혹은Add-Migration -ConfigurationTypeName EntityFrameworkTransactionScope.Data.FlightMigrations.Configuration "Initial"
마지막 으로 Update-database 를 통 해 데이터베이스 생 성 표 에 지속 적 으로 사용 해 야 합 니 다.Update-Database -ConfigurationTypeName EntityFrameworkTransactionScope.Data.FlightMigrations.Configuration
마찬가지 로 우 리 는 HotelDbContext 에 대해 상기 세 단계 명령 을 이용 하여 이전 을 한다.마지막 으로 우 리 는 모든 문맥 이 서로 다른 디 렉 터 리 로 이전 하 는 것 을 뚜렷하게 볼 수 있다.다음 과 같다.

위 이전 도 문제 가 없습니다.모든 컨 텍스트 를 따로 옮 겨 폴 더 를 만 듭 니 다.여러 컨 텍스트 를 같은 디 렉 터 리 폴 더 로 옮 기 고 구분 할 생각 이 있 습 니까?하나의 컨 텍스트 만 있 을 때 기본 으로 만 든 폴 더 는 Migrations 입 니 다.Migrations 폴 더 에서 서로 다른 컨 텍스트 이전 설정 을 만 듭 니 다.
여러 컨 텍스트 를 같은 폴 더 디 렉 터 리 로 옮 깁 니 다.
이것 은 사실 매우 간단 합 니 다.우 리 는-migration Directoty 뒤에서 특정한 폴 더 생 성 컨 텍스트 를 직접 지정 할 수 있 습 니 다.예 를 들 어 C:\A\DbContext,Entity Framework 도 이 점 을 해 냈 습 니 다.다음은 우리 가 살 펴 보 겠 습 니 다.Enable-Migrations -ContextTypeName FlightDbContext -MigrationsDirectory Migrations\FlightDbContext Enable-Migrations -ContextTypeName HotelDbContext -MigrationsDirectory Migrations\HotelDbContext나머지 두 단계 의 운행 방식 은 이전 과 마찬가지 로 결국 우 리 는 원 하 는 결 과 를 볼 수 있 을 것 이다.

상기 이전 을 통 해 최종 적 으로 FlightDb 와 ReservationDb 두 개의 데이터 베 이 스 를 생 성하 고 FlightBookings 와 Reservations 표 에 대응 합 니 다.자,여기 서 여러 문맥 이전 두 가지 방식 으로 끝 났 습 니 다.우 리 는 이 절의 화 제 를 계속 하 겠 습 니 다.
분산 사무
가끔 우 리 는 데이터 베 이 스 를 뛰 어 넘 는 관리 업무 가 필요 하 다.예 를 들 어 이런 장면 이 있 는데 두 개의 데이터 베이스 db1 과 db2 가 있 고 tb1 은 db1 에서 tb2 는 db2 에 있 으 며 tb1 과 tb2 는 관련 이 있다.상기 에서 우리 가 만 든 항공 편 과 예약 모델 은 우 리 는 항공 편 수 와 예약 데 이 터 를 서로 다른 데이터 베이스 에 동시에 삽입 해 야 한다.이때 업무 의 일치 성 을 요구한다.그래서 이러한 요 구 를 처리 하기 위해.NET 2.0 에서 System.Transaction 네 임 스페이스 에서 TransactionScope 류 를 제공 합 니 다.이러한 방식 은 코드 블록 을 업무 에 참여 시 키 고 업무 자체 와 상호작용 을 하지 않 아 도 되 는 간단 한 방식 을 제공 합 니 다.using 블록 에 TransactionScope 대상 을 만 드 는 것 을 강력 히 권장 합 니 다.
TransactionScope 가 실례 화 되 었 을 때,사무 관리 자 는 어떤 사무 에 참여 할 지 확인 해 야 합 니 다.일단 확정 되면,이 실례 는 업무 에 계속 참여 할 것 이다.TransactionScope 대상 을 만 들 때 다음 값 을 가 진 TransactionScopeOption 을 전달 해 야 합 니 다.
  • Required:인 스 턴 스 는 업무 가 필요 합 니 다.만약 업무 가 존재 한다 면 이미 존재 하 는 사 무 를 사용 해 야 합 니 다.그렇지 않 으 면 새로운 사 무 를 만 들 것 입 니 다
  • RequiresNew:항상 인 스 턴 스 를 위해 새로운 사 무 를 만 듭 니 다
  • 4.567917.Suppress:인 스 턴 스 를 만 들 때 다른 존재 하 는 업무 가 억 제 됩 니 다.이 인 스 턴 스 의 모든 작업 이 완료 되 었 기 때문에 다른 존재 하 는 업무 가 필요 하지 않 습 니 다그 다음 에 우 리 는 상기 매 거 진 두 번 째 방식 으로 항공 편 예약 을 실현 합 니 다.간단 한 논 리 는 다음 과 같 습 니 다.
    
    public class MakeReservation
     {
    
      FlightDBContext flight;
    
      HotelDBContext hotel;
    
      public MakeReservation()
      {
       flight = new FlightDBContext();
       hotel = new HotelDBContext();
      }
    
      //      
      public bool ReservTrip(TripReservation trip)
      {
       bool reserved = false;
    
       //        
       using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
       {
        try
        {
         //    
         flight.FlightBookings.Add(trip.Filght);
         flight.SaveChanges();
    
         //    
         hotel.Reservations.Add(trip.Hotel);
         hotel.SaveChanges();
    
         reserved = true;
    
         //       
         scope.Complete();
        }
        catch (Exception ex)
        {
         throw ex;
        }
       }
       return reserved;
      }
     }
    상기 ReservTrip 방법 은 TripReservation 대상 을 수락 합 니 다.이 방법 은 TransactionScope 를 정의 하고 트 랜 잭 션 의 컨 텍스트 에 Flight 와 Hotel 에 사용 할 Create 작업 을 묶 고 코드 를 try-catch 블록 에 기록 합 니 다.만약 두 실체의 SaveChanges 방법 이 성공 적 으로 실행 된다 면,사 무 는 완 료 될 것 입 니 다.그렇지 않 으 면 다시 굴 러 갈 것 입 니 다.다음은 컨트롤 러 호출.
    
    public class TripController : Controller
     {
      MakeReservation reserv;
    
      public TripController()
      {
       reserv = new MakeReservation();
      }
    
      public ActionResult Index()
      {
       return View();
      }
    
      public ActionResult Create()
      {
       return View(new TripReservation());
      }
    
      [HttpPost]
      public ActionResult Create(TripReservation tripinfo)
      {
       try
       {
        tripinfo.Filght.TravellingDate = DateTime.Now;
        tripinfo.Hotel.BookingDate = DateTime.Now;
        var res = reserv.ReservTrip(tripinfo);
    
        if (!res)
        {
         return View("Error");
        }
       }
       catch (Exception)
       {
        return View("Error");
       }
       return View("Success");
      }
     }
    우 리 는 항공 편 예약 보 기 를 추가 합 니 다.
    
    @model EntityFrameworkTransactionScope.Data.Entity.TripReservation
    
    @{
     ViewBag.Title = "Create";
    }
    
    <h2 class="text-center">    </h2>
    @using(Html.BeginForm()){
    
    
    <table class="table table-condensed table-striped table-bordered">
     <tr>
      <td>
       <table class="table table-condensed table-striped table-bordered">
        <tr>
         <td colspan="2" class="text-center">
              
         </td>
        </tr>
        <tr>
         <td>
            Id:
         </td>
         <td>
          @Html.EditorFor(m => m.Filght.FlightId)
         </td>
        </tr>
        <tr>
         <td>
              :
         </td>
         <td>
          @Html.EditorFor(m => m.Filght.FilghtName)
         </td>
        </tr>
        <tr>
         <td>
             :
         </td>
         <td>
          @Html.EditorFor(m => m.Filght.Number)
         </td>
        </tr>
       </table>
      </td>
      <td>
       <table class="table table-condensed table-striped table-bordered">
        <tr>
         <td colspan="2" class="text-center">
              
         </td>
        </tr>
        <tr>
         <td>
            Id:
         </td>
         <td>
          @Html.EditorFor(m => m.Hotel.BookingId)
         </td>
        </tr>
        <tr>
         <td>
              
         </td>
         <td>
          @Html.EditorFor(m => m.Hotel.Name)
         </td>
        </tr>
    
       </table>
      </td>
     </tr>
     <tr>
      <td colspan="2" class="text-center">
       <input type="submit" value="    " />
      </td>
     </tr>
    </table>
    
    }
    보기 보기 UI 는 다음 과 같 습 니 다.

    프로그램 을 실행 하고 사 무 를 검사 하려 면 분포 식 트 랜 잭 션 처리 코 디 네 이 터(DTC)서 비 스 를 사용 해 야 합 니 다.이 서 비 스 는 데이터베이스,메시지 대기 열,파일 시스템 등 두 개 이상 의 사무 가 보 호 된 자원 을 업데이트 하 는 것 을 조율 한다.우선 DTC 가 열 렸 는 지 확인 하고 서비스 에서 확인 하고 사용 해 야 합 니 다.

    다음은 DTC 설정 을 엽 니 다.다음 절차 에 따라 조작 하거나[dcomcnfg.exe]를 직접 실행 하여 구성 요소 서 비 스 를 한 단계 에 열 어 주 십시오.
    제어 판 을 열다관리 도 구 를 찾다.
    구성 요소 서 비 스 를 찾 습 니 다.

    이어서 우 리 는 관련 정 보 를 기입 하여 항공 편 예약 을 진행 할 것 이다.



    위 에 예약 이 완료 되 었 음 을 표시 하면 두 데이터베이스 에 있 는 데이터 가 올 바 르 게 삽입 되 었 는 지 확인 합 니 다.


    DTC 서비스 에서 제출 이 중단 되 지 않 을 때마다 제출 수량 이 1 증가 합 니 다.예약 모델 을 설정 할 때 저 희 는 메 인 키 를 표지 열 로 설정 하지 않 았 기 때문에 메 인 키 가 중복 되 는 상황 에서 표 의 데 이 터 를 다시 보 겠 습 니 다.우 리 는 세 번 제출 하고 예약 메 인 키 는 중복 되 지 않 습 니 다.네 번 째 때 메 인 키 는 세 번 째 메 인 키 로 입력 합 니 다.이때 결 과 를 보면 다음 과 같 습 니 다.




    저 희 는 leFlightBookings 와 Reservations 표 의 데 이 터 를 검증 하면 새로 추 가 된 기록 이 표시 되 지 않 습 니 다.이 는 TransactionScope 가 하나의 범위 에서 Flight 와 Hotel 데이터 베 이 스 를 연결 하여 Transaction 을 관리 하고 Committed 와 Aborted Transaction 을 모니터링 했다 는 뜻 이다.
    총결산
    EntityFramework 실체 프레임 워 크 를 개념 적 인 데이터 액세스 층 으로 사용 할 때 ASP.NET MVC 응용 프로그램 에서 보 듯 이 여러 개의 데이터 베 이 스 를 실행 하여 관련 데 이 터 를 저장 할 때 TransactionScope 를 사용 하여 업 무 를 관리 하 는 것 을 권장 합 니 다.

    좋은 웹페이지 즐겨찾기