【发布时间】:2014-06-18 08:13:09
【问题描述】:
EF 的非常奇怪的行为让我把头发拔了出来。
问题主要出在以下实体类,是封装的属性:
public class ContextParamValue
{
public Int64 Id { get; set; }
public Int64 ContextParamId { get; set; }
public virtual ContextParam ContextParam { get; set; }
public virtual ContextInstance ContextInstance { get; set; }
public Int64 ContextInstanceId { get; set; }
public string Value { get; set; }
}
如您所见,我有一个 ContextParamValue 类,它与 ContextParam 具有单向的 1 对 1 关系。因此,ContextParamValue 可以访问 ContextParam,但不能反过来。
让我崩溃的代码如下:
public List<ContextParamValue> ParamValuesToList(string[] ParamNames, string[] ParamValues)
{
if (ParamNames != null && ParamNames.Length != ParamValues.Length)
throw new System.ArgumentException("ParamNames and ParamValues may not differ in length.");
List<ContextParamValue> rList = new List<ContextParamValue>();
for (int i = 0; i < ParamNames.Length; i++)
{
string pName = ParamNames[i];
string pValue = ParamValues[i];
List<ContextParamValue> lst = db.ContextParamValues
//.Include(x => x.ContextParam)
.Where(pv => pv.ContextParam.Name.ToLower().Trim().Equals(pName.ToLower().Trim()))
.Where(pv => pv.Value.Equals(pValue))
.ToList<ContextParamValue>();
rList.AddRange(lst);
}
return rList;
}
这段代码的奇怪结果是ContextParam 只为rList 返回的第一个元素加载。 rList 中的所有后续元素的 ContextParam 属性都有一个空值。以下屏幕截图显示了调试期间的元素实例值:
集合中的第一个元素...获胜!
集合中的第二个元素...MASSIVE FAIL!
我已经为上述方法尝试了多种替代实现,即延迟加载、急切加载,甚至不从循环中构建列表(我构建了一个包含 ParamNames 和 ParamValues 数组对象的字典,它允许我在 LINQ 表达式中进行基于集合的匹配)。每次都是一样的结果。
我还包括了我的DbContext 类中的相关sn-ps:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
ModelMapper.InitializeRelationshipMappings(modelBuilder);
base.Configuration.LazyLoadingEnabled = true;
}
与
public static class ModelMapper
{
public static void InitializeRelationshipMappings(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
modelBuilder.Entity<Document>()
.HasRequired(d => d.FileItem)
.WithOptional(fi => fi.Document)
.WillCascadeOnDelete(true);
modelBuilder.Entity<Document>()
.HasMany(d => d.DocumentClasses)
.WithMany(dc => dc.Documents);
modelBuilder.Entity<ContextClass>()
.HasMany(cc => cc.RequiredClasses);
modelBuilder.Entity<ContextClass>()
.HasMany(cc => cc.OptionalClasses);
modelBuilder.Entity<ContextClass>()
.HasMany(cc => cc.Params)
.WithRequired(cp => cp.ContextClass)
.WillCascadeOnDelete(true);
modelBuilder.Entity<ContextInstance>()
.HasRequired(ci => ci.ContextClass);
modelBuilder.Entity<ContextInstance>()
.HasMany(ci => ci.ContextParamValues)
.WithRequired(cpv => cpv.ContextInstance)
.HasForeignKey(cpv => cpv.ContextInstanceId)
.WillCascadeOnDelete(true);
modelBuilder.Entity<ContextParamValue>()
.HasRequired(cpv => cpv.ContextParam);
}
}
【问题讨论】:
-
映射中缺少 ContextParam 是否有原因?
-
Ummm... 它没有丢失... 上面最后一个代码 sn-p 中的最后一条语句为:modelBuilder.Entity
() .HasRequired(cpv => cpv.ContextParam) ; -
谢谢。不幸的是,不是。
-
您是否调试过“for 循环”并观察循环的第二次迭代期间 ContextParam 属性发生了什么?它是否填充了来自数据库的信息?我很好奇名称和值是否仅与第一项匹配,而与其余项目不匹配。另一个问题:因为您正在转换为一个列表,我们是否可以假设存在多个具有相同名称和值的对象返回的实例?还是为了便于编写代码,只返回一个对象?
标签: c# entity-framework linq-to-entities entity-framework-6