使用EdmFunctionAttribute而不暴露Entity Framework依赖/实现细节?

时间:2010-05-10 19:34:20

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

是否有一种很好的方法可以在不引入对Entity Framework / System.Data.Entity.dll的依赖的情况下利用EdmFunctionAttribute

我以为我可以拥有一个方法和一个具体实现的接口,该实现使用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)
{
    ...
}

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

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

2 个答案:

答案 0 :(得分:1)

您是否可以使用Generic Repository Pattern并在其中公开IQueryable接口,例如:

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

答案 1 :(得分:0)

这是不可能的,因为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;
    }
}