.net 首先在实体框架4.1代码中附加缓存的断开连接的实体
我们有以下内容:Order with UserId和User table 假设我们希望将所有用户对象缓存为断开连接的实体,然后在ASP.NET或类似web服务的环境中使用它们 由于Environment使用UnitOfWork和IOC框架,我们希望避免任何上下文操纵。与以下单元测试类似:.net 首先在实体框架4.1代码中附加缓存的断开连接的实体,.net,entity-framework-4.1,ef-code-first,.net,Entity Framework 4.1,Ef Code First,我们有以下内容:Order with UserId和User table 假设我们希望将所有用户对象缓存为断开连接的实体,然后在ASP.NET或类似web服务的环境中使用它们 由于Environment使用UnitOfWork和IOC框架,我们希望避免任何上下文操纵。与以下单元测试类似: 获取断开连接的用户对象 创建上下文 创建订单对象 通过用户对象或id附加用户 保存整个Order对象 经过两天疯狂的谷歌搜索,我找不到任何解决办法 问题是: 1。用户对象 如果我们附加用户对象(userId=1
- 你建议做什么
- 是否有一种很好的通用方法可以使EFExtensionMethods.IsAttached从DbContext.SaveChanges开始工作
- 是否有一种很好的通用方法可以让EFExtensionMethods.AttachItem从DbContext.SaveChanges工作
[TestMethod]
public void使用用户和Id()创建订单
{
int userCount=CountAll();
用户;
使用(var db=GetContext()){user=db.Users.AsNoTracking().First();}
使用(var db=GetContext())
{
var o=CreateOrder();
o、 OrderUser=user;//附加用户实体
o、 UserId=user.UserId;//按id附加
db.Orders.加入(o);
db.SaveChanges();
}
int newUserCount=CountAll();
IsTrue(userCount==newUserCount,string.Format(“预期的{0}得到{1}”,userCount,newUserCount));
}
上下文和类:
公共类用户
{
公共用户(){}
public int UserID{get;set;}
公共字符串用户名{get;set;}
}
公共阶级秩序
{
公共秩序(){}
公共int-OrderID{get;set;}
public DateTime OrderDate{get;set;}
公共字符串OrderName{get;set;}
public int UserId{get;set;}
公共虚拟用户OrderUser{get;set;}
}
公共类医嘱配置:EntityTypeConfiguration
{
公共订单配置()
{
本表为ToTable(“订单”);
this.Property(x=>x.OrderName).HasMaxLength(200);
this.HasRequired(u=>u.OrderUser).WithMany().HasForeignKey(u=>u.UserId);
}
}
公共静态类EFExtensionMethods
{
//从DbContext.SaveChanges调用时不起作用,因为它认为T是一个对象。
公共静态bool已附加(此PPContext db,T实体),其中T:class
{
返回db.Set().Local.Any(e=>e==entity);
}
//从DbContext.SaveChanges调用时不起作用,因为它认为T是一个对象。
公共静态void AttachItem(此PPContext db,T实体),其中T:class
{
db.Set().Attach(实体);
}
}
公共类PPContext:DbContext
{
public PPContext():base(){}
公共PPContext(DbConnection-connection):基(connection,true){}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
添加(neworderconfiguration());
}
公共覆盖int SaveChanges()
{
var modified=ChangeTracker.Entries(),其中(e=>e.State==EntityState.modified | | e.State==EntityState.Added);
foreach(修改中的var项目)
{
????
}
}
公共数据库集用户{get;set;}
}
您的测试方法中不只是缺少一个附件
:
// ...
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
状态,当您调用SaveChanges
时,EF将创建一个新用户。我们已将标记界面添加到用户对象中,并将所有ICacheableEntity Entite标记为Entity。在SaveChanges中,我们只是将项目标记为未更改。这样就行了
public class User : ICacheableEntity
{
public User() { }
public int UserID {get;set;}
public string UserName {get;set;}
}
class PPContext
{
public bool IsSeeding {get;set;}
public override int SaveChanges()
{
var modified = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified || e.State == EntityState.Added);
if (!IsSeeding)
{
foreach (var item in modified.Where(item => (item.Entity is ICacheableEntity)))
{
item.State = EntityState.Unchanged;
}
}
}
}
谢谢Slauma。呼叫Attach正是我试图避免的。我想看看是否还有其他可能性,比如在SaveChanges方法中跟踪所有“添加”的实体,并将它们强制附加到上下文中。@b0rg:Hm,也许你接受我的答案太快了。我不想说除了调用
Attach
之外没有其他方法。我不知道你想避免这样。对于保存更改方法中的??可能类似于item.State=EntityState.Unchanged代码>是可能的。(但您必须将顺序与用户区分开来,因为两者都处于Added
状态。)但我不明白您为什么要避免Attach
。对我来说,这看起来容易多了。我还是个新手。你的答案是正确的,没有简单的方法。我想感谢你的努力