将'The member'转换为 SQL,这样它就不会引发'has no supported translation to SQL'



我最近一直在升级我的数据库,得到这个错误

基本上我所做的如下:

我有一个Participants表,其中有Name, First Name, E-mail address,…现在我已经将其重构为Persons表和Participants表。每个participant通过UUID链接到person。我已经从participants表中删除了NameFirst Name,它们现在在Persons表中。

In my Participants Partial Class:

public partial class Participant {
    public string Name {
        get {
            return this.Person.Name;
        }
    }
    public string FirstName {
        get {
            return this.Person.FirstName;
        }
    }

}

所以现在我的整个项目仍然可以找到这个名字,而且我不需要一次编辑很多代码。

然而,下面的查询给我带来了麻烦:

      _db.Participants.Where(q => whatever).OrderBy(q => q.Name).ThenBy(q => q.FirstName).ToList();

这会抛出臭名昭著的The member 'xxx.Models.Participants.Name' has no supported translation to SQL

是否有一种方法可以简单地告诉SQL生成器Participants.Name实际上是Participants.Person.Name ?

免责声明:如果您这样做是为了能够在不修改的情况下使用以前编写的查询,那么您就大错特错了。但是,如果您这样做是为了封装和代码管理,请继续阅读


有一个方法,但是有点笨拙。

首先,你将不得不添加表达式到你的Participant类(因为LINQ和EF工作与表达式,而不是已经编译的代码):

public partial class Participant
{
    public static readonly Expression<Func<Participant, string>>
        NameExpression = p => p.Person.Name;
    public static readonly Expression<Func<Participant, string>>
        FirstNameExpression = p => p.Person.FirstName;

你可以继续按照当前的方式使用你的属性:

    [NotMapped]
    public string Name
    {
        get
        {
            return this.Person.Name;
        }
    }
或者,为了减少代码的重复,可以引用静态表达式:
    [NotMapped]
    public string FirstName
    {
        get
        {
            return Participant.FirstNameExpression.Compile().Invoke(this);
            // if you do this, you might want to consider caching the delegate
            // returned by Expression.Compile()
        }
    }
}

最后,当您创建LINQ查询时,必须使用lambda语法,但是您可以使用您精心设计的表达式来代替直接写入查询中的特殊表达式:

IEnumerable<Participant> participants = _db.Participants
//  .Where(q => whatever)
    .OrderBy(Participant.NameExpression)
    .ThenBy(Participant.FirstNameExpression)
    .ToList();

如果我必须编辑查询,我不妨使用这样的扩展:

public static class MyExtensions {
    public static IQueryable<Participant> InDefaultOrder(this IQueryable<Participant> source) {
        return source.OrderBy(q => q.Person.Name).ThenBy(q => q.Person.FirstName);
    } 
}

那么我的查询将简单地是:_db.Participants.Where(q => whatever).InDefaultOrder().ToList();

如果它有变化,它将很容易编辑和维护。

—edit—

我还得加上这个

public static class MyExtensions {
    public static IEnumerable<Participant> InDefaultOrder(this IEnumerable<Participant> source) {
        return source.OrderBy(q => q.Person.Name).ThenBy(q => q.Person.FirstName);
    } 
}

相关内容

最新更新