我使用Code First来定义现有数据库的模式。我遇到的问题是他们在表格中的关键名称并不完全一致。这适用于一对多关系,因为我可以使用HasForeignKey()
方法,但似乎并不是一对一关系的等价物。我的表定义是:
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);
}
}
}
为了澄清模型,每个Document
都有DocType
,外键关系为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.ProsDocTypeId
和dbo.DocType.DocTypeId
之间创建一对一关系。 EF与之相关的问题是它只想使用主键创建关系,而不是外键。如何指定外键的列名,使每个Document
只有一个DocType
?
答案 0 :(得分: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]