我已经开始研究一个MVC 3项目,该项目需要来自庞大的现有数据库的数据。
我的第一个想法是继续使用EF 4.1并创建一堆POCO来表示我需要的表,但我开始认为映射会变得过于复杂,因为我只需要一些某些表格中的列。(感谢Steven在评论中的澄清。
所以我想我会试试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
的{{1}}对象,不定义任何上述方法;它通过覆盖DynamicObject
的DynamicModel
实现来处理它们:
TryInvokeMethod()
我对如何在public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args, out object result) { }
中“界面”这些方法感到茫然。我的ISession
如何为ISession
,First()
和Last()
提供支持?
换句话说,我如何使用所有的Massive功能,仍然可以将我的类与数据访问分离?
答案 0 :(得分:8)
我知道这个问题已得到解答 - 但Massive中的每个方法都标记为虚拟,因此您可以轻松地进行模拟。我可能会建议。或者 - 不要打扰。
我正在为我的MVC3视频项目做这个,并从Rails的剧本中获取一个页面 - 在我的对象上提供我的查询作为静态方法并从那里开始。我让我的测试进入数据库 - 它根本不会减慢速度,并且可以完全摆脱所有机器。
Rails中没有DI / IoC,这是一种快乐的感觉。
答案 1 :(得分:4)
界面
基本上,对于ISession的Find,Last和FindBy的签名,您有几个选项接口。
如果要保持与动态参数名称相同的语法First,Last和Find都应该是getter并使用实现bool TryInvoke(InvokeBinder binder, object[] args, out object result)
的DynamicObject返回dynamic,它将为您提供相同的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#编译器(including dynamic named parameters)一样。
var arg = InvokeArg.Create;
return Impromptu.InvokeMember(table, "Find", arg("column", val),arg("otherColum", otherVal));
或者您可以尝试伪造TryInvokeMember
;