우리는 다음을가집니다. UserId 및 User 테이블로 주문하십시오.Entity Framework 4.1에서 캐시 된 연결이 끊어진 엔터티 연결 코드 우선
모든 User 개체를 연결이 끊긴 엔터티로 캐시 한 다음 ASP.NET이나 웹 서비스 같은 환경에서 사용하려고한다고 가정 해 봅니다.
환경은 UnitOfWork 및 IOC 프레임 워크를 사용하기 때문에 컨텍스트 조작을 피하고자합니다. 단위 테스트는 다음과 같이 :
- 전체 주문 객체를 지속 사용자의 객체 또는 아이디를 통해 사용자를 연결합니다 주문 객체
- 을
- 상황을 만들기 연결이 끊긴 사용자 개체를 가져옵니다.
2 일 동안 맹렬한 인터넷 검색 결과를 얻지 못했습니다.
문제는 다음과 같습니다
1. 사용자 개체
우리는 사용자 개체를 연결하는 경우 (와 userId를 = 1) EF는 새로운 사용자이라고 생각 기본 동작과, 개체에 저장하고 새 사용자 개체를 db에 유지하려고합니다. db가 이미 userId == 1이기 때문에 불면합니다.
가능한 해결 방법은 DbContext.SaveChanges를 재정의하고 사용자가 "분리되어"강제로 컨텍스트에 첨부하는지 확인하는 것입니다. SaveChanges에서 호출 할 때 확장 메서드 EFExtensionMethods.IsAttached 또는 EFExtensionMethods.AttachItem이 T가 Object라고 생각하기 때문에이를 수행하는 방법을 알 수 없습니다.
2 USER_ID
이것은 당신이 지속 전체 개체를 다시로드하기 전에 Order.User 개체에 액세스 할 경우를 제외하고, 작동합니다.
그 위에 우리는 실제 개체 (Order.User)가 아닌 객체의 ID (즉, Order.UserId)만을 사용하여 저장하기 위해 API를 분할해야합니다. 객체를 다시로드 한 후에는 둘 다 사용할 수 있습니다. 그러나 API를 통해 실제로 적용 할 방법이 없다는 것을 알 수 있습니다.
3. BOTH 사용자 개체 및 사용자가 외부 키로 사용자 아이디를 사용하는 것으로 표시된 경우에도이 시나리오에서는
USER_ID는, EF는 여전히 1에서 설명하는 문제를 치는 상황에 사용자 개체를 저장하려고 . 내가 뭔가 (또는 많이)없는 것 같은
는 기본적인 외모와 질문은 다음과 같습니다
- 은 무엇 당신이 할 추천?
- 이는 DbContext에서 EFExtensionMethods.AttachItem 작업을 만드는 좋은 일반적인 방법이 있나요 DbContext.SaveChanges
- 에서 EFExtensionMethods.IsAttached 작품을 만드는 좋은 일반적인 방법입니다.저장 변경
도움을 주시면 대단히 감사하겠습니다.
[TestMethod]
public void Creating_Order_With_Both_User_And_Id()
{
int userCount = CountAll<User>();
User user;
using (var db = GetContext()) { user = db.Users.AsNoTracking().First(); }
using (var db = GetContext())
{
var o = CreateOrder();
o.OrderUser = user; // attach user entity
o.UserId = user.UserID; // attach by id
db.Orders.Add(o);
db.SaveChanges();
}
int newUserCount = CountAll<User>();
Assert.IsTrue(userCount == newUserCount, string.Format("Expected {0} got {1}", userCount, newUserCount));
}
컨텍스트 및 클래스 :
이// ...
using (var db = GetContext())
{
var o = CreateOrder();
db.Users.Attach(user);
o.OrderUser = user; // attach user entity
o.UserId = user.UserID; // attach by id
db.Orders.Add(o);
db.SaveChanges();
}
// ...
그렇지 않으면 EF가 Added
상태로 사용자를 넣어 것입니다 :
public class User
{
public User() {}
public int UserID {get;set;}
public string UserName {get;set;}
}
public class Order
{
public Order() { }
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public string OrderName { get; set; }
public int UserId { get; set; }
public virtual User OrderUser { get; set; }
}
public class OrderConfiguration : EntityTypeConfiguration<Order>
{
public OrderConfiguration()
{
this.ToTable("ORDERS");
this.Property(x => x.OrderName).HasMaxLength(200);
this.HasRequired(u => u.OrderUser).WithMany().HasForeignKey(u => u.UserId);
}
}
public static class EFExtensionMethods
{
// does not work, when called from DbContext.SaveChanges thinks T is an Object.
public static bool IsAttached<T>(this PPContext db, T entity) where T: class
{
return db.Set<T>().Local.Any(e => e == entity);
}
// does not work, when called from DbContext.SaveChanges thinks T is an Object.
public static void AttachItem<T>(this PPContext db, T entity) where T: class
{
db.Set<T>().Attach(entity);
}
}
public class PPContext : DbContext
{
public PPContext() : base() { }
public PPContext(DbConnection connection) : base(connection, true) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new OrderConfiguration());
}
public override int SaveChanges()
{
var modified = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified || e.State == EntityState.Added);
foreach (var item in modified)
{
????
}
}
public DbSet<User> Users {get;set;}
}
멋진 솔루션입니다! – Slauma
캐시 된 항목은 모두 불변입니까? 캐시 된 것처럼 보이므로 변경할 수 없습니까? 아니면 IsSeeding 플래그로 뭔가를하고 있습니까? – Jafin
캐시의 불변성은이 연습의 범위에서 고려되지 않습니다. 그리고 그것에 대해 더 생각할수록 중요하지 않습니다. 정말 :) – b0rg