12

我已经开始从事需要来自庞大现有数据库的数据的 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 基于一个dynamic名为的对象DynamicModel并没有定义上述任何方法;它通过TryInvokeMethod()重写的实现来处理它们DynamicObject

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

我不知道如何在我的ISession. 我如何为和提供ISession支持?First()Last()FindBy()

换句话说,我怎样才能使用Massive 的所有功能,并且仍然能够将我的类与数据访问分离?

4

2 回答 2

8

我知道这个问题已经回答了——但是 Massive 中的每个方法都被标记为虚拟的,所以你可以轻松地模拟它。我可能会建议。或者 - 不要打扰。

我目前正在我的项目中为 MVC3 视频执行此操作,并从 Rails 的剧本中获取一页 - 将我的查询作为我的对象的静态方法提供,然后从那里开始。我让我的测试进入数据库——它根本不会减慢速度,并且可以很自由地摆脱所有机器。

Rails 中没有 DI/IoC,感觉很幸福。

于 2011-06-30T21:21:12.447 回答
4

界面

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

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

    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;的参数。

于 2011-06-24T16:39:26.440 回答