![](/img/trans.png)
[英]How to create field and get data from joined table in Entity Framework 6
[英]Entity Framework - Custom Field that get data from another Table
我有這種情況:
public class Source
{
public int ID { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public virtual ICollection<InvoiceMembership> InvoiceMemberships { get; set;}
}
public class InvoiceMembership
{
public int ID { get; set; }
[Column(TypeName = "date")]
public DateTime StartDate { get; set; }
[Column(TypeName = "date")]
public DateTime? EndDate { get; set; }
public virtual Source source { get; set; }
public virtual InvoiceTemplate InvoiceTemplate { get; set; }
}
public class InvoiceTemplate
{
public int ID { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public bool Enabled { get; set; }
public int NumberOfPayment { get; set; }
}
如何在相關InvoiceMembership
行中具有EndDate=null
Source
實體中具有InvoiceTemplate
類型的名為CurrentTemplate
的字段?
編輯:
我使用波紋管代碼,但這不是真正的方法!
[NotMapped]
public InvoiceTemplate CurrentTemplate { get {
var context=new MedicalContext();
var template = context.InvoiceMemberships.Where(m => m.source == this).Where(m => m.EndDate == null).Select(m => m.InvoiceTemplate);
if (template != null)
return (InvoiceTemplate)template;
else
return null;
} }
是的,您可以,但是使用EF計算屬性非常麻煩。
假設您有:
public class Source
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
[NotMapped]
public InvoiceTemplate CurrentTemplate
{
get
{
return InvoiceMemberships
.Where(i = i.EndDate == null)
.Select(i => i.InvoiceTemplate)
.FirstOrDefault();
}
}
public virtual ICollection<InvoiceMembership> InvoiceMemberships { get; set;}
}
(我認為)要完成這項工作需要滿足太多條件:
CurrentTemplate
:EF會抱怨該表達式無法轉換為SQL。 Include()
InvoiceMemberships.InvoiceTemplate
才能訪問內存中的CurrentTemplate
。 這將始終為每個Source
對象加載所有 InvoiceMemberships
+ InvoiceTemplate
(在一個查詢中)。 Include()
,則只能在處置上下文之前訪問CurrentTemplate
。 這將在單獨的查詢中觸發每個Source
對象的所有 InvoiceMemberships
+ InvoiceTemplate
延遲加載。 如您所見, InvoiceMembership
每個Source
僅獲得一個InvoiceMembership
相比,您將總是加載(遠遠多於)所需的數據。
最有效的方法是將所需數據查詢到投影中,因此謂詞EndDate == null
可以包含在SQL查詢中。
我們將不得不等待NHibernate樣式的公式屬性。
直接在InvoiceMembership
POCO中公開您的外鍵值(如果存在關系,無論如何它都必須存在於數據庫中),並且整個查詢將通過L2E直接轉換為SQL:
public class InvoiceMembership
{
public int ID { get; set; }
public int SourceId { get; set; }
[ForeignKey("SourceId")]
public virtual Source Source { get; set; }
public virtual InvoiceTemplate InvoiceTemplate { get; set; }
}
並在Source
:
[NotMapped]
public InvoiceTemplate CurrentTemplate
{
get
{
using (var context = new MedicalContext())
return context.InvoiceMemberships
.Where(m => m.SourceId == this.ID)
.Where(m => m.EndDate == null)
.Select(m => m.InvoiceTemplate)
.FirstOrDefault();
}
}
但是,這樣做的缺點是-每次訪問該屬性時-都會查詢數據庫。 最好將此方法移至InvoiceMembership
類,在該類中您無論如何都將裝入InvoiceMembership
對象,並使其成為一種方法:
public class InvoiceMembership
{
public int ID { get; set; }
public int SourceId { get; set; }
[ForeignKey("SourceId")]
public virtual Source Source { get; set; }
public virtual InvoiceTemplate InvoiceTemplate { get; set; }
static public InvoiceTemplate ReadCurrentTemplate(int sourceId)
{
using (var context = new MedicalContext())
return context.InvoiceMemberships
.Where(m => m.SourceId == sourceId)
.Where(m => m.EndDate == null)
.Select(m => m.InvoiceTemplate)
.FirstOrDefault();
}
}
CurrentTemplate tells you that. 因此,現在,您有了一個方法 (而不是屬性),不再隱藏每次訪問該操作時都會執行的事實……名稱 CurrentTemplate告訴您。 為何現在不使其static
呢? 此外,將其設置為static
意味着您不再需要擔心NotMappedAttribute
。
但是我們仍然想在Source
進行訪問,不是ICollection<InvoiceMembership>
(特別是如果刪除ICollection<InvoiceMembership>
導航屬性,正如我希望在您的評論中看到的那樣)? 現在,這不再是EF的關注點,而是Source
類中的常規延遲加載(如果您願意)的關注點:
readonly Lazy<InvoiceTemplate> _currentTemplate;
public Source()
{
_currentTemplate = new Lazy<InvoiceTemplate>(t => t = InvoiceMembership.ReadCurrentTemplate(ID));
}
[NotMapped]
public InvoiceTemplate CurrentTemplate
{
get { return _currentTemplate.Value; }
}
因此,這樣做,您仍然需要運行數據庫查詢來獲取CurrentTemplate
的值,但是只有一次可以評估Lazy
私有支持者。 之后,在此Source
對象的生存期內,此屬性將與第一次讀取該屬性相同。 考慮到示例中它只是一個只讀屬性,因此這似乎符合您將如何使用它的模型。 而且僅在Source
對象的生存期內,無論如何都應在上下文中。
如果不是,這應該是方法ReadCurrentTemplate
(非static
的,沒有參數) Source
的歡迎,並簡單地返回InvoiceMembership.ReadCurrentTemplate(ID)
直接,表示每次它被稱為它是從數據庫中讀取。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.