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,但是 NHibernate 似乎并没有一致地创建代理,有时它会加载我的“代理类”类,有时它会加载“普通类”:
Person person = session.Load
(2); //这将很好地加载我的 Person 代理类 地址地址=人.地址; //不知何故,这不会加载地址代理,而是正常加载它 - 似乎它正在评估“ImmediateLoad”,由于延迟加载,它不会加载代理...不知道如何使其表现得像我一样想。 使用自定义 PropertyAccessor。我已经读过一些有关此内容的内容 - 但似乎我实际上必须将其映射到域类上 EXITS 的属性...这样就行不通,对吗?
就像 NHibernate 在创建 Proxy 类时将代码“注入”到运行时一样 - 也许我可以做同样的事情,但将“接口”注入到原始的 Person 类中?
I would like to "extend" my domain classes without having to add data to the domain classes themselves. Consider I have the following class:
public class Person
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
}
And I have the following table in the database:
tblPersons
---------------
Id integer
Name varchar(50)
CreatedBy varchar(50)
CreatedDate datetime
So I don't want to add "CreatedBy" and "CreatedDate" to my domain class, because this has nothing to do with the actual domain itself...
Would it be possible to get this data whenever I load an entity? I would like to use it like this:
Person person = session.Load<Person>(1);
person.CreatedBy(); <-- CreatedBy is an Extension function
person.CreatedDate(); <-- CreatedDate is an Extension function
Can anyone point me in which direction to go in order to implement this?
I have thought about the following possibilities:
Implement a custom ProxyFactory, where I inject a custom "interface" such as IUpdateable, howver it seems like NHibernate doesn't create the proxies consistently, sometimes it loads a my "proxy class" class, and sometimes it loads the "normal class":
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.
Using a custom PropertyAccessor. I have read something about this - but it seems I must actually map this to a property that EXITS on the domain class... so that wouldn't work, right?
Just as NHibernate "injects" code to the runtime when creating the Proxy classes - perhaps I could do the same but inject the "interface" to the original Person class instead?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用基类或组件映射轻松地完成此操作。我不会为此目的使用扩展方法。我使用一个基类:
流畅的映射:
如果您坚持将审计属性保留在类之外,则可以将审计属性映射为组件。
You can easily do this using a base class or a component mapping. I would not use extension methods for this purpose. I use a base class:
Fluent mapping:
If you are adamant about keeping audit properties out of your classes you could map the audit properties as a component.
这是一个想法。我从未实现过这一点,所以在测试之前请持保留态度。
创建一个不同的类来封装
Person
的审核数据 -PersonCreation
或其他内容。给它一个标识符、创建日期、创建者属性以及
Person
id 的属性(我认为不需要实际引用Person
,除非标识符是非公开,在这种情况下,您可能需要一个WeakReference
,这样您就不会在应用程序的生命周期中将每个Person
实例保留在内存中)。您需要为 NHibernate 创建映射以从
Person
表获取PersonCreation
对象。从这里,您可以简单地让扩展方法在调用时获取数据。这可能合理也可能不合理,具体取决于您的使用情况。您必须每次都创建一个新会话或同步静态会话。
或者...
在包含
CreatedBy()
和CreatedDate()
扩展方法的static
类中,创建一个静态IDictionary
保存每个Person
的详细信息。由于创建数据大概是不可变的,因此我们实际上不必担心它会变得陈旧。您需要使用
Person
查询对PersonCreation
进行批处理查询。例如,您可以执行以下操作:通过调用
Future()
,您可以告诉 NHibernate 在会话已经进入数据库之前不要执行该查询。获得结果后,您可以获取第一个创建结果并将其添加到字典中(以便扩展方法可以访问它),然后返回人员。
当您调用
person.CreatedDate()
时,该方法可以使用传递的Person
参数的 id 或Person
从字典中提取数据。代码> 本身。Here is one idea. I've never implemented this, so take it with a grain of salt until you've tested it.
Create a different class that encapsulates the audit data for
Person
--PersonCreation
or something.Give it an identifier, a created date, and created-by property, and a property for the
Person
id (I see no need actually reference thePerson
, unless the identifier is non-public, in which case you may want aWeakReference
so you don't keep everyPerson
instance in memory for the life of the application).You'll need to create a mapping for NHibernate to get
PersonCreation
objects from thePerson
table.From here, you could simply have the extension methods fetch data when called. This may or may not be reasonable depending on your usage. You'll have to create a new session every time or synchronize a static session.
Or…
In the
static
class that contains yourCreatedBy()
andCreatedDate()
extension methods, create a staticIDictionary<int, PersonCreation>
to hold the details for eachPerson
. Since creation data is presumably immutable, we don't really have to worry about this becoming stale.You'll want to batch queries for the
PersonCreation
with yourPerson
queries. For example, you could do something like:By calling
Future<T>()
, you're telling NHibernate not to execute that query until the session is already going to database anyway.Once you get results, you can take the first creation result and add it to the dictionary (so the extension methods have access to it), and return the person.
When you call
person.CreatedDate()
, the method can just pull the data from the dictionary using the id of the passedPerson
paramater, or thePerson
itself.