2010-08-01 98 views
2

我想“扩展”我的域类而不必将数据添加到域类本身。你看我有下面的类:NHibernate映射域“扩展属性”?

public class Person 
{ 
public virtual int Id { get; private set; } 
public virtual string Name { get; set; } 
} 

而且我在数据库如下表:

tblPersons 
--------------- 
Id integer 
Name varchar(50) 
CreatedBy varchar(50) 
CreatedDate datetime 

所以我不想“CreatedBy”和“CreatedDate”添加到我的领域类,因为这与实际域本身无关......

每当我加载一个实体时能得到这个数据吗?我想用这样的:

Person person = session.Load<Person>(1); 

person.CreatedBy(); <-- CreatedBy is an Extension function 
person.CreatedDate(); <-- CreatedDate is an Extension function 

任何人都可以点我在哪个方向,以实现该走?

我曾想过以下可能性:

  • 实现自定义ProxyFactory里,在那里我注入定制的“接口”,如IUpdateable,howver好像NHibernate的不创建代理始终如一,有时它加载了我的“代理类”级,有时它加载“正常班”:

    Person person = session.Load<Person>(2); //this will load my Proxy class of Person just fine 
    
    Address address = person.Address; //Somehow this doesn't load a Proxy for Address, but instead loads it normally - seems like it's evaluating "ImmediateLoad", which doesn't load proxies, due to lazy loading... not sure how to make this behave as I want. 
    
  • 使用自定义PropertyAccessor接口。我已阅读了关于此的一些信息 - 但似乎我必须实际将其映射到域类上的EXITS属性......所以这样做不行,对吧?就像NHibernate在创建代理类时向运行时“注入”代码一样 - 也许我可以做同样的事情,但是将“接口”注入原始Person类呢?

+0

当您不使用NHiberante时,扩展方法如何工作? – Paco 2010-08-01 12:11:57

+0

好吧,我使用NHibernate作为主题的含义。我已经使用“NHibernate Fluent”映射Person.Name属性以匹配数据库中的tblPersons.Name。 它不是c#的“扩展函数”,这是我的问题...这是我如何添加映射的NHibernate的Person类加载的CreatedDate/CreatedBy,但把这些值在一些外部结构或东西......是我不知道如何解决的。 谢谢, – Bilsa 2010-08-01 12:25:34

+0

没有NHiberante就无法完成,NHibernate无法完成。 – Paco 2010-08-01 20:09:08

回答

1

您可以使用基类或组件映射轻松地做到这一点。我不会为此使用扩展方法。我用一个基类:

public abstract class Auditable : IAuditable 
{ 
    public virtual string CreatedBy { get; set; } 
    public virtual DateTime CreatedDate { get; set; } 
} 

public class Person : Auditable {} 

流利的映射:

public class AuditableClassMap<T> : ClassMap<T> where T: IAuditable 
{ 
    public AuditableClassMap() 
    { 
     Map(x => x.CreatedBy); 
     Map(x => x.CreatedDate); 
    } 
} 

public class PersonMap : AuditableClassMap<Person> {} 

如果你是坚定的关于保持审计的属性你的类,你可以映射审计特性的组件。

+0

不错,谢谢 - 我真的不能改变领域类,但正如你所说 - 我不介意以其他方式映射它。您能否解释如何将审计属性映射为组件可以提供帮助? 我认为“组件映射”只是一种将扁平数据库列分组到域类中的更深层结构的方法? - 我将阅读Nhibernate中的组件。 感谢您的帮助! :) – Bilsa 2010-08-01 15:17:50

+0

如果你不能改变域类,那么我没有看到任何合理的方式来实现这一点。 – 2010-08-01 21:05:55

0

这是一个想法。我从来没有实现过这个,所以拿一粒盐直到你测试它。

创建一个不同的类,它封装审计数据Person - PersonCreation什么的。

给它一个标识符,创建日期和创建,通过属性,并为Person ID属性(我认为没有必要居然引用Person,除非标识符是不公开的,在这种情况下,你可能希望一个WeakReference,所以你不保存每个Person实例在内存中的应用程序的生命)。

您需要为NHibernate创建一个映射,以获取Person表中的PersonCreation对象。

从这里,您可以简单地使用扩展方法在调用时获取数据。这可能会也可能不合理,具体取决于您的使用情况。您必须每次创建新会话或同步静态会话。

或者......

在包含您的CreatedBy()CreatedDate()扩展方法的static类,创建一个静态IDictionary<int, PersonCreation>持有每个Person细节。由于创建数据大概是不可变的,所以我们不必担心这会变得过时。

您需要针对您的Person查询批量查询PersonCreation。例如,你可以这样做:

var creation = session.CreateCriteria<PersonCreation>() 
    .Add(Restrictions.Eq("PersonId", 1)) 
    .Future<PersonCreation>(); 

var person = session.CreateCriteria<Person>() 
    .Add(Restrictions.IdEq(1)) 
    .UniqueResult<Person>(); 

通过调用Future<T>(),你告诉NHibernate的不直到会议已经将数据库反正执行该查询。

获得结果后,您可以获取第一个创建结果并将其添加到字典中(以便扩展方法可以访问它)并返回该人员。

当您调用person.CreatedDate()时,该方法可以使用传递的参数Person参数的ID或Person本身从字典中提取数据。

+0

嘿周杰伦,谢谢! - 我会毫无顾忌地玩这个想法,谢谢一堆! :) – Bilsa 2010-08-03 01:21:15