Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 首先在实体框架4.1代码中附加缓存的断开连接的实体_.net_Entity Framework 4.1_Ef Code First - Fatal编程技术网

.net 首先在实体框架4.1代码中附加缓存的断开连接的实体

.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

我们有以下内容:Order with UserId和User table

假设我们希望将所有用户对象缓存为断开连接的实体,然后在ASP.NET或类似web服务的环境中使用它们

由于Environment使用UnitOfWork和IOC框架,我们希望避免任何上下文操纵。与以下单元测试类似:

  • 获取断开连接的用户对象
  • 创建上下文
  • 创建订单对象
  • 通过用户对象或id附加用户
  • 保存整个Order对象
  • 经过两天疯狂的谷歌搜索,我找不到任何解决办法

    问题是:

    1。用户对象

    如果我们附加用户对象(userId=1),默认情况下EF认为它是一个新的用户对象,并试图将新的用户对象持久化到db中。这是因为db已经有userId==1

    可能的解决方案是重写DbContext.SaveChanges,尝试确定用户是否“分离”,并强制将其附加到上下文。我不知道怎么做,因为从SaveChanges调用扩展方法EFExtensionMethods.IsAttached或EFExtensionMethods.AttachItem时,认为T是一个对象

    2。用户ID

    除非您希望在持久化和重新加载整个实体之前访问Order.User对象,否则这是有效的

    除此之外,我们还需要拆分API,以便只使用对象的id(即Order.UserId)而不是实际对象(Order.User)进行保存。重新加载对象后,我们可以同时使用这两种方法。但我看不出有什么办法可以通过API来实际执行它

    3。用户对象和用户ID两者

    在这种情况下,即使用户被标记为使用UserId作为外键,EF仍然试图将用户对象保存到上下文中,这会遇到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
    。对我来说,这看起来容易多了。我还是个新手。你的答案是正确的,没有简单的方法。我想感谢你的努力