2010-08-01 230 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