来自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
属性的空值。以下屏幕截图显示了调试期间的元素实例值:
集合中的第一个元素......赢取!
集合中的第二个元素......大失败!
我已经为上面的方法尝试了多种替代实现,即延迟加载,急切加载,甚至没有在循环中构建列表(我构建了ParamNames
和ParamValues
数组的字典允许我在LINQ表达式中进行基于集合的匹配的对象。每次都有相同的结果。
我还提供了DbContext
班级的相关摘要:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
ModelMapper.InitializeRelationshipMappings(modelBuilder);
base.Configuration.LazyLoadingEnabled = true;
}
AND
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);
}
}
答案 0 :(得分:0)
否则请尝试替换您的代码
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);
使用另一个LINQ
List<ContextParamValue> lst = from db.ContextParamValues.Where(pv => pv.ContextParam.Name.ToLower() == pName.ToLower().Trim()
&& db.ContextParamValues.Where(pv => pv.Value == pValue)).ToList<ContextParamValue>();
答案 1 :(得分:0)
for
循环放在using
块中:
using (var myDb = new MyDataContext())
{
for (int i = 0; i < ParamNames.Length; i++)
{
//etc., replacing "db" with "myDb"
}
}
我很想知道这是否有所改变。