2014-09-03 59 views
2

我使用Code First來定義現有數據庫的模式。我遇到的問題是他們在表中的關鍵名稱不完全對齊。這與一對多關係正常工作,因爲我可以使用HasForeignKey()方法,但似乎沒有一對一關係的等價物。我的表定義是:EF6 Code First - 使用不匹配的外鍵配置一對一關係

namespace Data.Mappings { 

    internal class DocumentTypeConfiguration : EntityTypeConfiguration<Document> { 

     public DocumentTypeConfiguration() { 
      ToTable("ProsDocs"); 

      HasKey(m => m.Id); 

      Property(m => m.Id) 
       .HasColumnName("ProsDocId") 
       .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

      // ---- This is the foreign key ---- 
      Property(m => m.TypeId) 
       .HasColumnName("ProsDocTypeId") 
       .HasMaxLength(3); 

      HasRequired(d => d.DocType) 
       .WithRequiredDependent(dt => dt.Document); 
       // I need to specify here that the foreign key is named "DocTypeId" and not "DocType_Id" 
     } 
    } 

    internal class DocTypeTypeConfiguration : EntityTypeConfiguration<DocType> { 

     public DocTypeTypeConfiguration() { 
      ToTable("DocType"); 

      HasKey(m => m.Id); 

      // ---- This is the "child" end of the foreign key ---- 
      Property(m => m.Id) 
       .HasColumnName("DocTypeId") 
       .HasMaxLength(4); 

      Property(m => m.FullName) 
       .HasColumnName("DocTypeDesc") 
       .HasMaxLength(255); 

      Property(m => m.Priority) 
       .HasColumnName("DocPriority"); 

      // Or would it be easier to define it here? 
//   HasRequired(m => m.Document) 
//    .WithRequiredDependent(d => d.DocType); 
     } 
    } 
} 

爲了澄清模型中,每個DocumentDocType,與Document.ProsDocTypeId --> DocType.Id的外鍵關係。

有沒有一種方法來定義什麼列名是鍵爲一對一的關係?

編輯:我想我的模式不清楚。

dbo.DocType 
----------- 
DocTypeId char(4) (PK) 
DocTypeDesc varchar(255) 

dbo.ProsDocs 
------------ 
ProsDocId int (PK) 
ProsDocTypeId char(4) 

基本上,我需要生成的查詢看起來像這樣:

SELECT 
    [Extent1].[ProsDocId] AS [ProsDocId], 
    [Extent2].[DocTypeId] AS [DocTypeId] 
    FROM [dbo].[ProsDocs] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[DocType] AS [Extent2] ON [Extent1].[ProsDocTypeId] = [Extent2].[DocTypeId] 
    WHERE [Extent1].[ProsId] = @EntityKeyValue1 

而是因爲EF假設我想使用的,而不是一個外鍵的主鍵(dbo.ProsDocs.ProsDocId)(dbo.ProsDocs.DocTypeId) ,它生成的查詢是這樣的:

SELECT 
    [Extent1].[ProsDocId] AS [ProsDocId], 
    [Extent2].[DocTypeId] AS [DocTypeId] 
    FROM [dbo].[ProsDocs] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[DocType] AS [Extent2] ON [Extent1].[ProsDocId] = [Extent2].[ProsDocTypeId] 
    WHERE [Extent1].[ProsId] = @EntityKeyValue1 

的區別就在這裏:

理想的查詢:

LEFT OUTER JOIN [dbo].[DocType] AS [Extent2] ON [Extent1].[ProsDocTypeId] = [Extent2].[DocTypeId] 

目前查詢:

LEFT OUTER JOIN [dbo].[DocType] AS [Extent2] ON [Extent1].[ProsDocId] = [Extent2].[ProsDocTypeId] 

我需要創建dbo.ProsDocs.ProsDocTypeIddbo.DocType.DocTypeId之間的一個一對一的關係。 EF遇到的問題是,它只想使用主鍵創建關係,而不是使用外鍵。如何指定每個Document只有一個DocType的外鍵列名稱?

+0

哪一個是主體(必須先存在的實體)? – 2014-09-03 16:53:54

回答

3

如果Document是委託人和DocType是相關的,那麼你要麼需要

  • Document

    HasRequired(d => d.DocType).WithRequiredPrincipal(dt => dt.Document); 
    
  • 此類配置,或者在DocType

    這種配置
    HasRequired(dt => dt.Document).WithRequiredDependent(d => d.DocType); 
    

並刪除TypeId/ProsDocTypeId屬性Document作爲主體不能有外鍵id依賴,除非它不是一個約束,只是一個普通的列。

更新

實體:

public class Document 
{ 
    public string Id { get; set; } 
    // This entity is a principal. It can't have foreign key id to dependent. 
    // public string TypeId { get; set; } 
    public DocType DocType { get; set; } 
} 

的Linq:

db.Documents.Include(d => d.DocType) 

查詢:

SELECT 
    1 AS [C1], 
    [Extent1].[ProsDocId] AS [ProsDocId], 
    [Extent2].[DocTypeId] AS [DocTypeId], 
    FROM [dbo].[ProsDocs] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[DocType] AS [Extent2] ON [Extent1].[ProsDocId] = [Extent2].[DocTypeId] 

更新2

要實現理想的查詢,您需要的關係是一對多關係。一個DocType可以有很多Document

public class Document 
{ 
    public string Id { get; set; } 
    public string TypeId { get; set; } 
    public DocType DocType { get; set; } 
} 
public class DocType 
{ 
    public string Id { get; set; } 
    public string FullName { get; set; } 
    public string Priority { get; set; } 
    public ICollection<Document> Documents { get; set; } 
} 

Document上的配置。

更改此:

HasRequired(d => d.DocType).WithRequiredDependent(dt => dt.Document); 

分爲:

HasRequired(d => d.DocType).WithMany(dt => dt.Documents).HasForeignKey(d => d.TypeId); 

的Linq:

db.Documents.Include(d => d.DocType) 

查詢:

SELECT 
    1 AS [C1], 
    [Extent1].[ProsDocId] AS [ProsDocId], 
    [Extent1].[ProsDocTypeId] AS [ProsDocTypeId], 
    [Extent2].[DocTypeId] AS [DocTypeId], 
    FROM [dbo].[ProsDocs] AS [Extent1] 
    INNER JOIN [dbo].[DocType] AS [Extent2] ON [Extent1].[ProsDocTypeId] = [Extent2].DocTypeId] 
+0

這正是我的問題。正如我的模型所示,「Document」的主鍵是'ProsDocId'。關係應該在'Document.TypeId'和'DocType.Id'之間,或者換言之,'dbo.Document'是主體,而'dbo.DocType.DocTypeId'是外鍵。看到我更新的問題。 – 2014-09-03 17:47:16

+0

@StephenCollins,我認爲你對這種關係中的一對一關係的定義感到困惑,就像你提到的那樣(文檔是主體),校長**不能**有另一個列指依賴於像'Document.TypeId'到'DocType.Id',關係應該在'Document.Id'到'DocType.Id'之間,請檢查[這個一對一的關係](http://www.databaseprimer.com/ pages/relationship_1to1 /)其中'Customer'表(主體)不能有像CustomerDetailId這樣的其他列,我的答案保持不變,只需添加實體並查詢 – 2014-09-04 02:56:41

+0

無論我的錯誤是否不正確,答案仍然不是解決我的問題。我需要將結果查詢作爲我的問題中的第一個查詢(「理想查詢」)。該查詢正是我在自定義SQL中執行的操作;我需要Linq中的等價物。 – 2014-09-04 03:01:49

相關問題