EntityFramework 6.x 학습 의 여러 상하 문 이전 실현 분포 식 사무 상세 설명
16910 단어 entityframework6.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 을 전달 해 야 합 니 다.
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 를 사용 하여 업 무 를 관리 하 는 것 을 권장 합 니 다.