C# EF代码优先:具有不同键名的关系
我有两张桌子:C# EF代码优先:具有不同键名的关系,c#,sql,linq,entity-framework,entity-framework-6.1,C#,Sql,Linq,Entity Framework,Entity Framework 6.1,我有两张桌子: DocumentSet: setId (int) name (varchar(50)) DocIdentifier: docIdId (int) docSetId (int) <-- (setId from DocumentSet) customId (char(9)) 请注意命名差异:setId和docSetId是用于外键的列。当我尝试在实体框架中复制这个时,问题就出现了。我有明显的模式: class DocumentSet { public int Id {
DocumentSet:
setId (int)
name (varchar(50))
DocIdentifier:
docIdId (int)
docSetId (int) <-- (setId from DocumentSet)
customId (char(9))
请注意命名差异:setId
和docSetId
是用于外键的列。当我尝试在实体框架中复制这个时,问题就出现了。我有明显的模式:
class DocumentSet {
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<DocumentIdentifier> Identifiers {get;set;}
}
class DocumentIdentifier {
public int Id {get;set;}
public int SetId {get;set;}
public string CustomId {get;set;}
public DocumentSet DocSet {get;set;}
}
问题是:当我发送这样的LINQ查询时:
_context.Set<DocumentSet>().Where(d => d.DocumentIdentifiers.Any(pt=>pt.CustomId == customId)).Single();
我猜问题在于setId
和docSetId
是不同的名称,但我似乎不知道如何让EF看到[Extent2].[DocumentSet\u Id]
应该是[Extent2].[docSet\u Id]
。在DocumentIdentifierTypeConfiguration
中是否有我遗漏的东西可以帮助EF理解这一点?我认为行属性(f=>f.SetId)
会这样做,但显然不会
简言之,我该怎么说
`DocumentSet has many DocumentIdentifiers with a foreign key relationship of DocumentSet.setId = DocIdentifier.docSetId`?
尝试添加和删除
完整代码
public class AppContext : DbContext
{
public DbSet<DocumentSet> DocumentSets { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DocumentSetTypeConfiguration());
modelBuilder.Configurations.Add(new DocumentIdentifierTypeConfiguration());
}
}
public class DocumentSetTypeConfiguration : EntityTypeConfiguration<DocumentSet>
{
public DocumentSetTypeConfiguration()
{
HasKey(f => f.Id);
Property(f => f.Id).HasColumnName("setId");
HasMany(f => f.DocumentIdentifiers).WithRequired().HasForeignKey(x => x.SetId);
}
}
public class DocumentIdentifierTypeConfiguration : EntityTypeConfiguration<DocumentIdentifier>
{
public DocumentIdentifierTypeConfiguration()
{
ToTable("DocIdentifier");
HasKey(f => f.Id);
Property(f => f.Id).HasColumnName("docIdId");
Property(f => f.SetId).HasColumnName("docSetId");
}
}
public class DocumentSet
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<DocumentIdentifier> DocumentIdentifiers { get; set; }
}
public class DocumentIdentifier
{
public int Id { get; set; }
public int SetId { get; set; }
public string CustomId { get; set; }
}
这很好(经过一些修改,见我的答案)。现在我必须弄清楚为什么EF突然不再实际连接到数据库…@StephenCollins,你不必添加
DocSet
(但如果你愿意,你可以),只要尝试添加上面的代码,它就可以工作,WithRequired
可以在指定HasMany
后接受空参数,如果使用MapKey
,则类public int SetId{get;set;}
中的外键值将不会作为外键连接。您的建议听起来不错,但问题还是在于命名。您的建议给我带来了一个modelvalidateexception
,而MapKey
方法将正确生成模型/查询,但问题在于:有许多(ds=>ds.Identifiers).WithRequired().Map(di=>di.MapKey(“docSetId”)代码>。这会失败,因为它告诉我`类型中的每个属性名称都必须是唯一的。属性名“docSetId”已经定义。`@StephenCollins,我发布了完整的代码和结果,您能指出缺少什么吗?您的代码在新项目中运行良好。我必须有我的代码中没有注意到的其他问题。我还有更多的挖掘工作要做。非常感谢。
SELECT TOP (2)
[Extent1].[SetId] AS [SetId],
[Extent1].[Name] AS [Name]
FROM [dbo].[DocumentSet] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[DocIdentifier] AS [Extent2]
WHERE ([Extent1].[SetId] = [Extent2].[DocumentSet_Id]) AND (([Extent2].CustomId = @p__linq__0) OR (([Extent2].[CustomId] IS NULL) AND (@p__linq__0 IS NULL)))
)
`DocumentSet has many DocumentIdentifiers with a foreign key relationship of DocumentSet.setId = DocIdentifier.docSetId`?
HasMany(f => f.Identifiers).WithRequired().HasForeignKey(x => x.SetId);
public class AppContext : DbContext
{
public DbSet<DocumentSet> DocumentSets { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DocumentSetTypeConfiguration());
modelBuilder.Configurations.Add(new DocumentIdentifierTypeConfiguration());
}
}
public class DocumentSetTypeConfiguration : EntityTypeConfiguration<DocumentSet>
{
public DocumentSetTypeConfiguration()
{
HasKey(f => f.Id);
Property(f => f.Id).HasColumnName("setId");
HasMany(f => f.DocumentIdentifiers).WithRequired().HasForeignKey(x => x.SetId);
}
}
public class DocumentIdentifierTypeConfiguration : EntityTypeConfiguration<DocumentIdentifier>
{
public DocumentIdentifierTypeConfiguration()
{
ToTable("DocIdentifier");
HasKey(f => f.Id);
Property(f => f.Id).HasColumnName("docIdId");
Property(f => f.SetId).HasColumnName("docSetId");
}
}
public class DocumentSet
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<DocumentIdentifier> DocumentIdentifiers { get; set; }
}
public class DocumentIdentifier
{
public int Id { get; set; }
public int SetId { get; set; }
public string CustomId { get; set; }
}
SELECT TOP (2)
[Extent1].[setId] AS [setId],
[Extent1].[Name] AS [Name]
FROM [dbo].[DocumentSets] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[DocIdentifier] AS [Extent2]
WHERE ([Extent1].[setId] = [Extent2].[docSetId])
AND (([Extent2].[CustomId] = @p__linq__0)
OR (([Extent2].[CustomId] IS NULL) AND (@p__linq__0 IS NULL)))
)