LINQ to Entities不支持指定的类型成员。仅支持初始化程序,实体成员和实体导航属性


71
var result =
    (from bd in context.tblBasicDetails
     from pd in context.tblPersonalDetails.Where(x => x.UserId == bd.UserId).DefaultIfEmpty()
     from opd in context.tblOtherPersonalDetails.Where(x => x.UserId == bd.UserId).DefaultIfEmpty()
     select new clsProfileDate()
     {
         DOB = pd.DOB
     });

foreach (clsProfileDate prod in result)
{
    prod.dtDOB = !string.IsNullOrEmpty(prod.DOB) ? Convert.ToDateTime(prod.DOB) : DateTime.Today;
    int now = int.Parse(DateTime.Today.ToString("yyyyMMdd"));
    int dob = int.Parse(prod.dtDOB.ToString("yyyyMMdd"));
    string dif = (now - dob).ToString();
    string age = "0";
    if (dif.Length > 4)
    age = dif.Substring(0, dif.Length - 4);
    prod.Age = Convert.ToInt32(age);
}

GetFinalResult(result);

protected void GetFinalResult(IQueryable<clsProfileDate> result)
{
    int from;
    bool bfrom = Int32.TryParse(ddlAgeFrom.SelectedValue, out from);
    int to;
    bool bto = Int32.TryParse(ddlAgeTo.SelectedValue, out to);

    result = result.AsQueryable().Where(p => p.Age >= from);
}

在这里,我得到一个例外:

LINQ to Entities不支持指定的类型成员“年龄”。仅支持初始化程序,实体成员和实体导航属性。

在数据库中没有Age的地方,这是我在clsProfileDate类中创建的属性,用于根据DOB计算Age。有什么解决办法吗?

Answers:


99

您不能使用未映射到Where表达式中数据库列的属性。您必须基于映射的属性构建表达式,例如:

var date = DateTime.Now.AddYears(-from);
result = result.Where(p => date >= p.DOB);
// you don't need `AsQueryable()` here because result is an `IQueryable` anyway

作为您未映射Age属性的替代,您可以将此表达式提取到静态方法中,如下所示:

public class clsProfileDate
{
    // ...
    public DateTime DOB { get; set; } // property mapped to DB table column

    public static Expression<Func<clsProfileDate, bool>> IsOlderThan(int age)
    {
        var date = DateTime.Now.AddYears(-age);
        return p => date >= p.DOB;
    }
}

然后以这种方式使用它:

result = result.Where(clsProfileDate.IsOlderThan(from));

在下面除了检查hp93的答案,from a in db.aitems select new Model { A = a.A }在这里这可查询的,你必须全部explecitly指定要在使用属性Where,所以在这里你可以过滤或群体,或命令只能由A,因为你已经映射仅适用于A -A = a.A
尼基塔

20

很多人会说这是一个不好的答案,因为这不是最佳实践,但是您也可以在未使用位置之前将其转换为列表。

result = result.ToList().Where(p => date >= p.DOB);

Slauma的答案更好,但这也行得通。这会花费更多,因为ToList()将针对数据库执行查询并将结果移到内存中。


4
感觉很脏,但小剂量有效。
AGB

9
ToList被调用时,查询将被执行并且不必要的数据将被加载到内存中。因此最好在编码上有一些限制!
Paridokht

这对我有好处,因为我的问题属性在Sum Linq函数中,而不在Where子句中。因此,我没有得到不必要的数据,并且在检索的数据上,我正在执行在列表上使用的Linq Sum函数。谢谢!一开始看起来很糟的东西在某些情况下可能会很有帮助!
Dov Miller

这对我来说非常有用,因为我们正在修改一个字段,以便根据另一个字段中的布尔值在其上添加数据。(标记项已停用),直到我在中间插入清单,它一直拒绝工作。
约翰·罗德,

我需要什么!
Sharif Yazdian

14

当您不小心忘记为属性定义setter时,也会收到此错误消息。例如:

public class Building
{
    public string Description { get; }
}

var query = 
    from building in context.Buildings
    select new
    {
        Desc = building.Description
    };
int count = query.ToList();

调用ToList将给出相同的错误消息。这是一个非常微妙的错误,很难检测到。


经过一些愚蠢的重构,这就是我的意思。
菲尔·库珀

1
但是,如果它是不可更新的SQL视图,为什么我需要二传手?
ARLibertarian

1
不要紧。实体框架仍然需要一种设置属性的方法。在普通的C#代码中,您将无法执行以下操作:Building b = new Building(); b.Description =“测试”;
马塞尔·杰利克

2

我忘了选择列(或将属性设置/映射到列值):

IQueryable<SampleTable> queryable = from t in dbcontext.SampleTable
                                    where ...
                                    select new DataModel { Name = t.Name };

queryable.OrderBy("Id")即使DataModelId定义属性,调用也会引发异常。

正确的查询是:

IQueryable<SampleTable> queryable = from t in dbcontext.SampleTable
                                    where ...
                                    select new DataModel { Name = t.Name, Id = t.Id };

2

就我而言,即使我的应用程序的二进制文件是相同的,我也只是在生产环境中才收到此错误消息,而在本地运行时却没有。

在我的应用程序中,我使用的是自定义设置,DbModelStore以便将运行时生成的EDMX保存到磁盘并在启动时从磁盘加载(而不是从头开始重新生成),以减少应用程序的启动时间-并且由于我的代码中的错误,不会使磁盘上的EDMX文件失效-因此Production在从磁盘上引用了较旧版本的EDMX文件,该文件引用了我在异常错误消息中重命名类型名称之前的应用程序类型的较旧版本。

删除高速缓存文件并重新启动应用程序,将其修复。


1

在这种情况下,最简单,最好的方法之一是先将其转换为list,然后使用whereor select

result = result.ToList().where(p => date >= p.DOB);

0

在WHERE子句之前检查Count()解决了我的问题。它比ToList()便宜

if (authUserList != null && _list.Count() > 0)
    _list = _list.Where(l => authUserList.Contains(l.CreateUserId));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.