通过接口属性 LINQ to Entities

Posted

技术标签:

【中文标题】通过接口属性 LINQ to Entities【英文标题】:LINQ to Entities through Interface Property 【发布时间】:2012-03-08 17:56:04 【问题描述】:

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

但是,当我尝试针对这些接口方法编写 LINQ to entity 查询时,我得到了 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();
    

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

但是有没有办法实现这种模式。理想情况下,每个功能领域都有业务逻辑单元,处理接口并映射到所有相关实体。 但这意味着 EF 之上的另一个“映射”层,它将您的业务逻辑接口属性转换为真正的 EF 属性。此映射层还将转换查询。我不称之为这种模式——我称之为架构应用程序。 可能架构过度,但是如何避免将相同的代码复制并粘贴到多个业务层对象中,以便它们可以执行相同的逻辑,但使用不同命名的实体属性? 这个问题太抽象了,无法回答——唯一的反应可能是:重构。只需您有一个 EF 模型,并且您想在某处定义 L2E 查询 =>“某处”必须使用真正的 EF 映射属性。您所有的附加属性“名称”都是多余的。 我想我可能没有足够详细地解释问题域。感谢您的回复,我会重新考虑我的问题。【参考方案2】:

您可以使用动态查询库 (http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx)。

        if (typeof (INamedEntity).IsAssignableFrom(typeof (T)))
        
            q = q.Where("ID ==@0", id);
        

【讨论】:

【参考方案3】:

在基于泛型源和 where 子句中使用的接口成员的查询执行期间发生以下异常。

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

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

参考:Interface not supported

【讨论】:

是的,这看起来是个问题。

以上是关于通过接口属性 LINQ to Entities的主要内容,如果未能解决你的问题,请参考以下文章

LINQ to SQL查询基于使用外键与使用内置导航属性成功或失败

实现接口的 LINQ to SQL 类

Linq to NHibernate ThenFetch 多个属性

LinQ to SQL用法详解

C# LINQ-to-XML 选择子元素属性最大的元素

LinQ to SQL 查询