我注意到EF出現了一個奇怪的事件,並且它確定了在評估.Include(x=x.T)
語句時它將使用哪些字段。確定連接表外鍵列名的約定
在我們的項目中,我們所有的數據庫表(以及EF的POCO)的前綴都是DB
,所涉及的兩個表格分別是DBTemplates
和DBItems
。每個項目都有一個與其關聯的(可選)模板。
相關的線在我們DbContext
此:
public IDbSet<DBTemplate> Templates {get;set;}
public IDbSet<DBItem> Items {get;set;}
爲簡單起見,假設這兩個表包含一個標識和名稱屬性以及具有一個外鍵回到DBTemplates的DBItems表。這是(現在)叫做Template_Id
(我會解釋一下爲什麼),但是一般來說我們會把它命名爲DBTemplateId
。
一般來說,我們有一個名爲db
的變量,它是我們的DbContext
的一個實例。
最初創建DBItem
定義的開發人員添加了虛擬屬性鏈接到相關DBTemplate
,但省略了外鍵。屬性是這樣的:
public class DBItem
{
public System.Guid Id { get; set; }
public string Name { get; set; }
public virtual DBTemplate Template { get; set; }
}
public class DBTemplate
{
public System.Int32 Id { get; set; }
public string Name { get; set; }
}
當查詢項目,下面的語句被擊中
db.Items.Include(i=>i.Template)
和下面的SQL生成
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent2].[Id] AS [Id1],
[Extent2].[Name] AS [Name1],
FROM [dbo].[DBItems] AS [Extent1]
LEFT OUTER JOIN [dbo].[DBTemplates] AS [Extent2] ON [Extent1].[Template_Id] = [Extent2].[Id]
到目前爲止,一切都很好。但是,我現在需要(也應該有)DBItem對象上的Template_Id
。當我把它添加到DBItem類,所以它看起來像這樣:
public class DBItem
{
public System.Guid Id { get; set; }
public string Name { get; set; }
public Nullable<System.Int32> Template_Id { get; set; }
public virtual DBTemplate Template { get; set; }
}
同一行被擊中,但SQL生成這個樣子的,現在
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Template_Id] AS [Template_Id],
[Extent2].[Id] AS [Id1],
[Extent2].[Name] AS [Name1],
FROM [dbo].[DBItems] AS [Extent1]
LEFT OUTER JOIN [dbo].[DBTemplates] AS [Extent2] ON [Extent1].[Template_Id1] = [Extent2].[Id]
(注意Template_Id1爲加入)
現在,這個問題很容易解決,因爲我可以告訴模型構建器尋找名爲Template_Id
的外鍵,並且一切都很好。
builder.Entity<DBItem>().HasOptional(x => x.Template).WithMany().HasForeignKey(x => x.Template_Id);
然而,如果公約之後,並命名爲DBTemplateId
領域,以及DBItem類是這樣的:
public class DBItem
{
public System.Guid Id { get; set; }
public string Name { get; set; }
public Nullable<System.Int32> DBTemplateId { get; set; }
public virtual DBTemplate Template { get; set; }
}
,而無需修改模型構建器屬性(讓EF接管純粹約定),它正確地將DBTemplateId屬性作爲外鍵,並生成SQL,如下所示:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[DBTemplateId] AS [DBTemplateId],
[Extent2].[Id] AS [Id1],
[Extent2].[Name] AS [Name1],
FROM [dbo].[DBItems] AS [Extent1]
LEFT OUTER JOIN [dbo].[DBTemplates] AS [Extent2] ON [Extent1].[DBTemplateId] = [Extent2].[Id]
,並且查詢按預期工作(同樣不太容易出錯的C#代碼)。
顯然,這裏的教訓是要遵循的字段命名的模式,但爲什麼EF自動查找和使用屬性名作爲連接鍵命名爲DBTemplateId
,但查找重複Template_Id1
當存在於POCO Template_Id
什麼時候?
對我來說是有意義的,有沒有一個地方這是記錄? –
我不知道官方的Microsoft文檔在哪裏。我已經在「程序設計實體框架:代碼優先」一書中詳細閱讀了它,在這裏很好地解釋了這一點。 –