【问题标题】:Use EdmFunctionAttribute without exposing Entity Framework dependency/implementation details?使用 EdmFunctionAttribute 而不暴露实体框架依赖项/实现细节?
【发布时间】:2011-02-17 20:23:12
【问题描述】:

有没有一种很好的方法来利用EdmFunctionAttribute 而不会引入对实体框架/System.Data.Entity.dll 的依赖?

我想我可以有一个带有方法的接口和一个具体的实现,该实现使用EdmFunctionAttribute 将其映射到数据库函数。

我在一个程序集中定义了一个上下文接口IMyContext,在另一个程序集中定义了一个实体框架实现MyContext

public interface IMyContext
{
    double SomeFunction(double first, double second);

    // other interface details here
}

public partial class MyContext : IMyContext
{
    [EdmFunction("MyNamespace", "MyDatabaseFunction")]
    public double SomeFunction(double first, double second)
    {
        throw new NotSupportedException("This method may only be called as part of a LINQ expression.");
    }

    // rest of interface implementation here
}

我使用工厂(在幕后使用 StructureMap)来获取上下文实例作为接口类型:

using (IMyContext context = ContextFactory.GetNewContext())
{
    var results = context.Table.Select(t => context.SomeFunction(t.Col1, t.Col2)).ToList();
}

这会引发NotSupportException,表示 LINQ to Entities 无法识别方法“Double SomeFunction(Double, Double)”。

如果我将上下文转换为具体实现

using (MyContext context = ContextFactory.GetNewContext() as MyContext)
{
    ...
}

然后它可以工作,但是我需要指定具体的实现,我不想这样做。

函数不必是上下文类的成员,我只是把它放在那里进行探索。

【问题讨论】:

  • 我面临着同样的情况。我也希望 EdmFunctionAttribute 在通过接口引用访问时能够得到解决,但无济于事。当使用多个上下文(多个数据库)时,它变得更加困难。
  • 对于它的价值,我无法解决这个问题,不得不在我的存储库(在你的情况下为上下文)的具体实现上使用 DB 函数,这意味着所有函数调用都必须驻留在我的存储库类——即:我的客户端代码无法直接访问它。我对此并不感到兴奋,但它确实有效(并且它强制查询代码驻留在存储库中,有些人会认为它属于它的位置)。

标签: c# entity-framework .net-4.0 dependencies


【解决方案1】:

你能不能不使用Generic Repository Pattern 并在那里公开IQueryable 接口作为方法,比如:

IQueryable FindAll(Func<T,bool> exp);

【讨论】:

    【解决方案2】:

    这是不可能的,因为 Linq 查询生成器将调查接口类型而不是具体类。表达式树将包含接口方法的方法引用,当您调查方法的属性时,它不会返回任何属性。

    您可以创建一个表达式访问器并访问您的表达式树并将类型从接口更改为具体类型。

    TypeReplacer tr = new TypeReplacer();
    tr.Visit(ex);
    
    class TypeReplacer: ExpressionVisitor{
        protected override MethodCallExpression MethodCall(MethodCallExpression exp)
        {
           // compare exp.Method and 
           // replace it with concrete Type's method
           return exp;
        }
    }
    

    【讨论】:

    • 抱歉,您的回答不能解决问题中尚未实施的任何问题。您的解决方案仍然需要引用具体的上下文类而不是上下文接口。
    猜你喜欢
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 2023-03-08
    相关资源
    最近更新 更多