我有以下实体:
public class ModuleCriteria
{
public int ModuleCriteriaId { get; set; }
public string Criteria { get; set; }
public List<ModuleCriteriaLookup> ModuleCriteriaLookups { get; set;
}
}
public class ModuleCriteriaLookup
{
public int ModuleCriteriaLookupId { get; set; }
public int ModuleCriteriaId { get; set; } // ** (Foreign Key) **
public int SiteId { get; set; }
public string CategoryId { get; set; }
public ModuleCriteria ModuleCriteria { get; set; }
}
我的Context
课程(为简洁起见编辑)中有以下EF配置:
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating( modelBuilder );
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<ModuleCriteriaLookup>().HasRequired( mc => mc.ModuleCriteria );
// I tried adding the below line but it made no difference.
//modelBuilder.Entity<ModuleCriteria>().HasMany( mc => mc.ModuleCriteriaLookups );
}
...我在DbSet
类中定义了以下Context
属性:
public DbSet<ModuleCriteria> ModuleCriteria { get; set; }
public DbSet<ModuleCriteriaLookup> ModuleCriteriaLookup { get; set; }
我有一个CriteriaRepository
类,它有一个Save
方法,用于对ModuleCriteria
个实体进行持久更改:
public void Save( ModuleCriteria moduleCriteria )
{
using ( var ctx = new MyAppContext() )
{
ctx.Entry( moduleCriteria ).State = moduleCriteria.ModuleCriteriaId == 0 ? EntityState.Added : EntityState.Modified;
ctx.SaveChanges();
}
}
ModuleCriteria
对象可以在没有ModuleCriteriaLookup
对象的情况下存在,但ModuleCriteriaLookup
对象必须与现有的ModuleCriteria
对象相关(在ModuleCriteriaId
上相关)。
您可以拥有多个ModuleCriteraLookup
个对象,这些对象都与同一个ModuleCriteria
对象相关。
我希望和EF期望的行为是:
1)如果我创建一个新的ModuleCriteria
对象(没有任何ModuleCriteriaLookups
),请调用我的存储库中的Save
方法,我希望看到新的ModuleCriteria
记录在数据库中,数据库中没有相关的ModuleCriteriaLookup
记录。
2)如果我创建一个新的ModuleCriteria
对象并为其分配List<ModuleCriteriaLookup>
,请调用我的存储库中的Save方法,我希望在db中看到新的ModuleCriteria
记录数据库中的x个新ModuleCriteriaLookup
行与该特定ModuleCriteria
相关。
3)如果我添加/编辑/删除与我的ModuleCriteriaLookup
个对象之一相关的任何ModuleCriteria
个对象,那么调用我的存储库中的Save
方法,我希望要查看要从数据库中删除的ModuleCriteria
个已删除ModuleCriteriaLookup
个对象,添加任何新对象以及任何已编辑的对象只是为了更新。
所以我需要担心的是,无论ModuleCriteria.ModuleCriteriaLookups
属性包含给定ModuleCriteria
的内容,只需调用Save方法即可在数据库的2个表中反映出来。我的存储库中的ModuleCriteria
对象。
不幸的是,目前,如果我添加一个关联ModuleCriteria
的新List<ModuleCriteriaLookup>
对象,它会很好地在db中添加ModuleCriteria
和x ModuleCriteriaLookup
行。但是当我想编辑或删除ModuleCriteria.ModuleCriteriaLookups
属性中的条目时,这不会反映在数据库中。 ModuleCriteriaLookups
行没有任何结果。
我不确定问题究竟在哪里,无论是EF映射配置还是与存储库如何工作有关?
答案 0 :(得分:1)
问题位于存储库中。 DbContext
需要了解实体的存在。因此,在编辑和/或删除实体时,需要首先从数据库中提取实体。
这description明确指出:
.Entry
属性返回正在进行的上下文中的对象 跟踪背景。
因为您在创建上下文后立即直接使用此属性,所以上下文不跟踪这些实体,因此不知道某些内容已更改。因此无法生成正确的SQL语句。
根据您的其他设计,有几种方法可以解决这个问题。
删除它的一种方法是:
public void DeleteModuleCriteriaLookup(ModuleCriteriaLookup[] lookups)
{
using (var ctx = new MyAppContext())
{
var moduleCriteriaId = lookups.First().ModuleCriteriaId;
var moduleCritria = (
from criteria in ctx.ModuleCriteria
where criteria.ModuleCriteriaId == moduleCriteriaId
select criteria
).Single();
var lookupIdsToDelete = lookups.Select(l => l.ModuleCriteriaLookupId);
var lookupsToDelete = (
from lookup in moduleCritria.ModuleCriteriaLookups
where lookupIdsToDelete.Contains(lookup.ModuleCriteriaLookupId)
select lookup
).ToArray();
foreach (var lookup in lookupsToDelete)
{
moduleCritria.ModuleCriteriaLookups.Remove(lookup);
}
ctx.SaveChanges();
}
}