C# 在实体框架中手动更新已修改的集合状态

C# 在实体框架中手动更新已修改的集合状态,c#,entity-framework,C#,Entity Framework,我在添加或删除设置了AutoDetectChangesEnabled=false的实体的关系时遇到一些问题。示例模型和代码如下所示: public class Category : Entity { public Guid CategoryId { get; set; } public virtual ICollection<UserProfile> UserProfiles { get; set; } public string N

我在添加或删除设置了
AutoDetectChangesEnabled=false
的实体的关系时遇到一些问题。示例模型和代码如下所示:

public class Category : Entity
{
    public Guid CategoryId { get; set; }        
    public virtual ICollection<UserProfile> UserProfiles { get; set; }     
    public string Name { get; set; }
}

public class UserProfile : Entity
{
    public Guid UserProfileId { get; set; }

    public virtual ICollection<Category> Categories { get; set; }
    public string Name { get; set; }
}

var context = new OfContext();
context.Configuration.AutoDetectChangesEnabled = false;

var userProfile = context.UserProfiles
                         .Include(up => up.Categories)
                         .FirstOrDefault(up => up.UserProfileId == new Guid("XXXX"));
var category = context.Categories
                      .FirstOrDefault(c => c.CategoryId == new Guid("XXXX"));

userProfile.Categories.Add(category);
userProfile.Name = "Updated";
context.Entry(userProfile).State = EntityState.Modified;
context.SaveChanges();

但我看不到任何类似的情况表明集合已被更改。

您可以使用
context.ChangeTracker.DetectChanges()
来执行此操作,EF将检查条目是否已更改,然后标记将被分配到数据库中,因此您只需在
保存更改之前更改此方法,请执行以下代码:

public class Category : Entity
{
    public Guid CategoryId { get; set; }        
    public virtual ICollection<UserProfile> UserProfiles { get; set; }     
    public string Name { get; set; }
}

public class UserProfile : Entity
{
    public Guid UserProfileId { get; set; }

    public virtual ICollection<Category> Categories { get; set; }
    public string Name { get; set; }
}

var context = new OfContext();
context.Configuration.AutoDetectChangesEnabled = false;
var userProfile = context.UserProfiles.Include(up => up.Categories).FirstOrDefault(up => up.UserProfileId == new Guid("XXXX"));
var category = context.Categories.FirstOrDefault(c => c.CategoryId == new Guid("XXXX"));
userProfile.Categories.Add(category);
userProfile.FirstName = "Updated";
context.Entry(userProfile).State = EntityState.Modified;
context.ChangeTracker.DetectChanges();
context.SaveChanges();
如果不使用DetectChanges方法,则可以这样使用ObjectStateManager

var context = new OfContext();
context.Configuration.AutoDetectChangesEnabled = false;
var userProfile = context.UserProfiles.Include(up => up.Categories).FirstOrDefault(up => up.UserProfileId == new Guid("XXXX"));
var category = context.Categories.FirstOrDefault(c => c.CategoryId == new Guid("XXXX"));
userProfile.Categories.Add(category);
userProfile.FirstName = "Updated";
var objectStateManager = ((IObjectContextAdapter)context).ObjectContext.ObjectStateManager;
objectStateManager.ChangeRelationshipState(userProfile, category, x => x.Categories, EntityState.Added);
objectStateManager.ChangeObjectState(userProfile, EntityState.Modified);
context.SaveChanges();                    
这条线

objectStateManager.ChangeObjectState(userProfile,EntityState.Modified)

将处理FirstName属性和任何其他简单属性的修改

这条线呢

objectStateManager.ChangeRelationshipState(userProfile, category, x => x.Categories, EntityState.Added);

将处理类别属性的关系修改。

ChangeTracker
类不保存有关模型状态的所有数据。它只包含实体状态的数据,而不包含独立关联状态的数据,如多对多关系(如本文所述)

这些更改在
ObjectStateManager
类中跟踪。您应该能够使用
changelationshipstate
方法将两个实体之间的关系标记为已更改(请参阅)

旁注-要为
DbContext
获取
ObjectStateManager
,必须将
DbContext
强制转换为
ObjectContext

var objectStateManager = 
    ((IObjectContextAdapter)dbcontext).ObjectContext.ObjectStateManager;

感谢您的输入,这看起来确实有效,但是有没有办法手动设置该状态(类似于Entry().state),这样就不需要调用DetectChanges()?它大概是在设置某些内容的状态,以便SaveChanges()知道要更新什么。再次感谢您提供的信息。@Domtar您为什么要从DetectChanges中退出?你为什么需要手动操作?@Domtar我更改了答案以适应你的问题,没有使用DetectChanges。太好了,谢谢你提供的信息。在AutoDetectChanges方面,我们正在导入大量关系,并且我们正在使用的存储库(genericunitofworkandrepositories.codeplex.com)让我们手动设置内容的状态。这么多的关系中,唯一的东西,那里没有手动设置。我想如果我已经为90%的更改设置了状态,为什么还要检查所有其他检测更改代码。谢谢您的回复。@Domtar Np,遗憾的是,这对正确答案都没有用处。
objectStateManager.ChangeRelationshipState(userProfile, category, x => x.Categories, EntityState.Added);
var objectStateManager = 
    ((IObjectContextAdapter)dbcontext).ObjectContext.ObjectStateManager;