大规模ORM依赖注入:动态问题

本文关键字:动态 问题 注入 ORM 依赖 大规模 | 更新日期: 2023-09-27 18:00:03

我已经开始处理一个MVC 3项目,该项目需要来自庞大的现有数据库的数据。

我的第一个想法是继续使用EF 4.1并创建一堆POCO来表示我需要的表,但我开始认为映射会变得过于复杂,因为我只需要一些表中的一些列(感谢史蒂文在评论中的澄清。

所以我想试试Massive ORM。我通常使用工作单元实现,这样我就可以很好地保持一切解耦,并可以使用依赖注入。这是我对Massive:的一部分

public interface ISession
{
    DynamicModel CreateTable<T>() where T : DynamicModel, new();
    dynamic Single<T>(string where, params object[] args) 
        where T : DynamicModel, new();
    dynamic Single<T>(object key, string columns = "*") 
        where T : DynamicModel, new();
    // Some more methods supported by Massive here
}

下面是我对上述接口的实现:

public class MassiveSession : ISession
{
    public DynamicModel CreateTable<T>() where T : DynamicModel, new()
    {
        return new T();
    }
    public dynamic Single<T>(string where, params object[] args) 
        where T: DynamicModel, new()
    {
        var table = CreateTable<T>();
        return table.Single(where, args);
    }
    public dynamic Single<T>(object key, string columns = "*") 
        where T: DynamicModel, new()
    {
        var table = CreateTable<T>();
        return table.Single(key, columns);
    }
}

问题出现在First()Last()FindBy()方法中。Massive基于一个名为DynamicModeldynamic对象,没有定义任何上述方法;它通过DynamicObject替代的TryInvokeMethod()实现来处理它们:

public override bool TryInvokeMember(InvokeMemberBinder binder, 
    object[] args, out object result) { }

我不知道如何在ISession中"接口"这些方法。我的ISession如何为First()Last()FindBy()提供支持?

换句话说,我如何使用Massive的所有功能,并且仍然能够将我的类与数据访问解耦?

大规模ORM依赖注入:动态问题

我知道这个问题已经得到了答案,但Massive中的每个方法都被标记为虚拟的,所以你可以很容易地模拟它。我可能会这么建议。或者——不用麻烦了。

我目前在我的项目中为MVC3视频做这件事,并借鉴Rails的剧本——将我的查询作为对象上的静态方法提供,然后从那里开始。我让我的测试进入数据库——它一点也不会减慢速度,而且可以很自由地摆脱所有的机器。

Rails中没有DI/IoC,这是一种快乐的感觉。

接口

基本上,对于ISession的Find、Last和FindBy的签名,您有几个接口选项。

如果您希望使用动态参数名称First、Last和Find保持相同的语法,则它们都应该是getter,并使用实现bool TryInvoke(InvokeBinder binder, object[] args, out object result)的DynamicObject返回dynamic,该DynamicObject将为您提供相同的dynamic Find(column:val, otherColum:otherVal)语法。以下是一个粗略的基本示例:

    public class MassiveSession : ISession
{ 
    ...
    public dynamic Find{
           get {
               return new DynamicInvoker(this,name:"Find");
           }
    }
    public class DynamicInvoker : DynamicObject{
        ...
        public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
        {
             ...
             return true;          
        }
    }
}

如果你想要完全静态定义的方法,你只需要做一个IDictionary或其他的参数来给你密钥对。

将调用转发到Massive动态方法

还有两种方法可以做到这一点。

简单的方法是使用开源框架ImpromptuInterface,它允许您像c#编译器一样以编程方式调用动态方法(包括动态命名参数)。

var arg = InvokeArg.Create;
return Impromptu.InvokeMember(table, "Find", arg("column", val),arg("otherColum", otherVal));

或者你可以试着伪造进入TryInvokeMember的参数;