我想“扩展”我的域类,而不必将数据添加到域类本身。考虑我有以下课程:
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,似乎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在创建Proxy类时“注入”代码到运行时一样 - 也许我可以这样做但是将“接口”注入到原来的Person类中?
答案 0 :(得分: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> {}
如果您坚持要将审计属性保留在类之外,则可以将审计属性映射为组件。
答案 1 :(得分:0)
这是一个想法。我从来没有实现过这个,所以在你测试它之前先拿一点盐。
创建一个不同的类,用于封装Person
- PersonCreation
或其他内容的审核数据。
为它提供标识符,创建日期和created-by属性,以及Person
id的属性(我看不需要实际引用Person
,除非标识符是非公开的,在这种情况下,您可能需要WeakReference
,因此在应用程序的生命周期内不会将每个Person
实例保留在内存中。
您需要为NHibernate创建一个映射,以便从PersonCreation
表中获取Person
个对象。
从这里开始,您可以简单地让扩展方法在调用时获取数据。根据您的使用情况,这可能合理也可能不合理。您必须每次都创建一个新会话或同步一个静态会话。
或者...
在包含static
和CreatedBy()
扩展方法的CreatedDate()
课程中,创建一个静态IDictionary<int, PersonCreation>
来保存每个Person
的详细信息。由于创建数据可能是不可改变的,因此我们不必担心这种情况会变得陈旧。
您需要使用PersonCreation
查询批量查询Person
。例如,您可以执行以下操作:
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
本身从字典中提取数据。