EF Code First DbContext仅为集合的第一个元素返回封装实体

时间:2014-05-01 19:03:22

标签: c# entity-framework linq-to-entities entity-framework-6

来自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属性的空值。以下屏幕截图显示了调试期间的元素实例值:

First element in the list is A-OK 集合中的第一个元素......赢取!

Subsequent elements... HUGE FAIL 集合中的第二个元素......大失败!

我已经为上面的方法尝试了多种替代实现,即延迟加载,急切加载,甚至没有在循环中构建列表(我构建了ParamNamesParamValues数组的字典允许我在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);
    }
}

2 个答案:

答案 0 :(得分:0)

  1. 请检查这是否与数据相关。
  2. 否则请尝试替换您的代码

       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);
    
  3. 使用另一个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>();
    
    • 这可能是一个上下文问题,因为它无法加载或无法执行linq.Try注释您的代码&amp;我相信你可以用SP来获取这些数据(我做了同样的事情并且有效)

答案 1 :(得分:0)

请告诉我幽默。将整个for循环放在using块中:

using (var myDb = new MyDataContext()) 
{
   for (int i = 0; i < ParamNames.Length; i++)
   { 
     //etc., replacing "db" with "myDb" 
   }
}

我很想知道这是否有所改变。