通过接口属性使用LINQ to Entities

9

我有一个情况,希望使用单个业务逻辑类来执行各种实体框架类的类似操作。我已经在部分类文件中定义了一个这些类实现的接口。

但是,当我尝试针对这些接口方法编写LINQ to entities查询时,由于查询未直接使用类的属性而是通过接口进行访问,因此会引发NotSupportedException异常。

我希望将大部分工作留给数据库层,那么有没有一种方法可以实现这一点而不必借助LINQ to objects呢?

以下是演示我的问题的一些代码(它使用一个由工厂创建的通用存储库类)。

public interface INamedEntity
{
    int ID { get; set; }
    string Name { get; set; }
}

// This is an Entity Framework class which has CustomerID and CustomerName properties.
public partial class Customer: INamedEntity
{
    int INamedEntity.ID
    {
        get { return this.CustomerID; }
        set { this.CustomerID = value; }
    }
    string INamedEntity.Name
    {
        get { return this.CustomerName; }
        set { this.CustomerName = value; }
    }
}

...

public string GetName<T>(int entityID) where T: EntityObject, INamedEntity
{
    using(var repository = RepositoryFactory.CreateRepository<T>())
    {
        return repository
            .Where(e => e.ID == entityID)
            .Select(e.Name)
            .Single();
    }
}
3个回答

6

不支持此功能。您的Linq-to-entities查询只能使用实体的映射属性。如果使用接口属性,EF不知道如何将其转换为SQL,因为它无法分析属性实现中的代码。

不要对实体使用接口- EF根本不支持它。在您的特殊情况下,即使使用任何其他ORM,它也不起作用,因为您正在查询未知于映射的属性。这将要求您构建自己的Linq提供程序,将查询转换为具有真正映射属性的查询。


但是有没有办法实现这种模式呢?理想情况下,每个功能区域都有专门的业务逻辑单元,使用接口进行工作,并映射到所有相关实体。 - gareththegeek
1
但这意味着在EF之上又有了另一个“映射”层,它将把您的业务逻辑接口属性转换为真正的EF属性。这个映射层还将转换查询。我不称之为模式 - 我称之为过度架构化的应用程序。 - Ladislav Mrnka
或许有点过度设计,但是你该如何避免将相同的代码复制粘贴到多个业务层对象中,以便它们可以执行相同的逻辑,但使用不同命名的实体属性呢? - gareththegeek
这是一个太抽象的问题无法回答 - 唯一的反应就是:重构。简单来说,你有一个 EF 模型,并且想要在某个地方定义 L2E 查询 => 那个“某个地方”必须使用真实的 EF 映射属性。你所有额外的属性“名称”都是多余的。 - Ladislav Mrnka
我认为可能我没有充分详细地解释问题领域。谢谢你们的回复,我会重新考虑我的问题。 - gareththegeek
这真是个令人沮丧的事情,我很高兴我没有花太多时间去尝试。 - Jesse

2

0

在基于通用源并使用 where 子句中的接口成员进行查询执行期间,会出现以下异常。

NotSupportedException: 不支持接口成员 [InterfaceName].[MemberName] 的映射。

只有当查询应返回多个项且使用 == 运算符时才会出现异常。当使用 First、FirstOrDefault 或 Single 执行查询或在 where 子句中使用 equals 或其他运算符时,我无法重现此错误。

参考:不支持的接口


是的,那看起来就是问题所在。 - gareththegeek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接