2014-09-03 57 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

相关问题