我正在使用的当前系统利用Castle Activerecord在Domain对象和数据库之间提供ORM(对象关系映射).这一切都很好,在大多数情况下实际上运作良好!
问题出在Castle Activerecords支持异步执行,更具体地说是管理对象所属会话的SessionScope.长话短说,坏事发生了!
因此,我们正在寻找一种方法来轻松转换(自动思考)从Domain对象(谁知道数据库存在和关心)到DTO对象(谁对DB一无所知,不关心会话,映射属性或所有事物) ORM).
有没有人有这样做的建议.首先,我正在寻找对象的基本一对一映射.域对象Person将被映射为PersonDTO.我不想手动这样做,因为它是浪费.
很明显,人们会想到反思,但我希望在这个网站周围有一些更好的IT知识 可以提出"更酷".
哦,我正在使用C#,ORM对象在使用Castle ActiveRecord映射之前说过.
通过@ ajmastrean的请求,我已经链接到一个我(非常)嘲弄在一起的例子.该示例具有捕获表单,捕获表单控制器,域对象,activerecord 存储库和异步帮助程序.它有点大(3MB),因为我包含了运行它所需的ActiveRecored dll.您需要在本地计算机上创建一个名为ActiveRecordAsync的数据库,或者只需更改.config文件.
示例的基本细节:
捕获表格
捕获表单引用了控制器
private CompanyCaptureController MyController { get; set; }
在表单的初始化时,它调用MyController.Load()private void InitForm(){MyController = new CompanyCaptureController(this); MyController.Load(); 这将返回一个名为LoadComplete()的方法
public void LoadCompleted (Company loadCompany) { _context.Post(delegate { CurrentItem = loadCompany; bindingSource.DataSource = CurrentItem; bindingSource.ResetCurrentItem(); //TOTO: This line will thow the exception since the session scope used to fetch loadCompany is now gone. grdEmployees.DataSource = loadCompany.Employees; }, null); } }
这是"坏东西"发生的地方,因为我们正在使用设置为延迟加载的公司子列表.
控制器
控制器有一个从表单调用的Load方法,然后调用Asyc助手来异步调用LoadCompany方法,然后返回到Capture表单的LoadComplete方法.
public void Load () { new AsyncListLoad().BeginLoad(LoadCompany, Form.LoadCompleted); }
LoadCompany()方法只是使用存储库来查找已知公司.
public Company LoadCompany() { return ActiveRecordRepository.Find(Setup.company.Identifier); }
该示例的其余部分相当通用,它有两个继承自基类的域类,一个用于检查某些数据的安装文件,以及用于提供ActiveRecordMediator功能的存储库.
我解决了一个与此非常类似的问题,我将大量旧Web服务合同中的数据复制到WCF数据协定中.我创建了许多具有如下签名的方法:
public static T ChangeType(this S source) where T : class, new()
第一次在此方法(或任何其他重载)执行用于两种类型,它着眼于每种类型的属性,并决定其在两个基于名称和类型存在的.这需要这种"构件相交",并使用DynamicMethod的类来EMIL的IL到源类型复制到目标类型,则它缓存在一个线程静态辞典所得委托.
一旦创建了委托,它的速度非常快,我提供了其他重载来传递委托来复制与交集标准不匹配的属性:
public static T ChangeType(this S source, ActionadditionalOperations) where T : class, new()
...所以你可以为你的Person to PersonDTO例子这样做:
Person p = new Person( /* set whatever */); PersonDTO = p.ChangeType();
而两个人及PersonDTO(同样具有相同的名称和类型)的任何属性将被运行时发出的方法复制和任何后续调用就不会被发射,但会重复使用相同发出代码为这些类型顺序(即将PersonDTO复制到Person也会产生命中以发出代码).
发布的代码太多了,但如果您有兴趣,我会努力将样本上传到SkyDrive并在此处发布链接.
理查德