我們有以下內容:使用UserId和User表進行排序。在Entity Framework中附加緩存的斷開連接的實體4.1代碼優先
比方說,我們希望將所有用戶對象緩存爲斷開連接的實體,然後在ASP.NET或Web服務(如環境)中使用它們。
由於環境使用UnitOfWork和IOC框架,我們希望避免任何上下文操作。就像下面的單元測試:
- 斷開連接的用戶對象
- 創建上下文
- 創建訂單對象
- 通過用戶對象或id連接用戶
- 堅持整個訂單的對象。
經過兩天的使用google搜索,我找不到任何解決方案。
的問題是:
1.用戶對象
如果我們連接的用戶對象(用戶id = 1),默認行爲EF認爲它是一個新用戶對象,並試圖將新的用戶對象保存到數據庫中。這是因爲db已經有userId == 1.
可能的解決方案是重寫DbContext.SaveChanges,試圖找出用戶是否「分離」並強制將其附加到上下文。我想不出如何做到這一點,因爲從SaveChanges調用時擴展方法EFExtensionMethods.IsAttached或EFExtensionMethods.AttachItem認爲T是一個對象。
2. USER_ID
這工作,當你想堅持,並重新加載整個實體之前訪問Order.User對象除外。
最重要的是,我們需要拆分API,以便僅保存使用對象的id(即Order.UserId)而不保存實際對象(Order.User)。重新加載對象後,我們可以同時使用這兩個對象。但我看不到通過API實際執行它的方法。
3 BOTH用戶對象並USER_ID
,即使用戶被標記爲使用用戶ID作爲外鍵這種情況下,EF仍試圖保存用戶對象爲背景擊中1所描述的問題。
看起來像我失去了一些東西(或很多)的原理和問題是:
- 什麼,你會推薦做?
- 有來自DbContext.SaveChanges
- 使EFExtensionMethods.IsAttached工作的很好的和通用的方式是有來自的DbContext使EFExtensionMethods.AttachItem工作的好和通用的方式。SaveChanges
任何幫助,非常感謝。
[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));
}
語境和類:
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