EntityFramework:模型1:0..1与流利的api +约定的关系 [英] EntityFramework: Model 1:0..1 relationship with fluent api + conventions
问题描述
我从edmx模型生成以下类:
I have the following classes generated from an edmx model:
public partial class A
{
public int Id { get; set; }
public virtual B B { get; set; }
}
public partial class B
{
public int Id { get; set; }
public virtual A A { get; set; }
}
现有数据库未使用EF默认值,该默认值期望A.Id是表B的主键:
The existing db doesn't use the EF default which expects A.Id to be the primary key of table B:
CREATE TABLE [dbo].[B] (
[Id] INT IDENTITY (1, 1) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
CREATE TABLE [dbo].[A] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[BId] INT NULL,
CONSTRAINT [fk] FOREIGN KEY ([BId]) REFERENCES [dbo].[B] ([Id])
);
使用edmx模型,我可以显式配置每个端点的多样性,但是我还没有找到如何使用fluent-api获得等效模型的方法.当我执行以下操作并生成新的数据库时,外键将放置在表A中而不是表B中.
With an edmx model, I can explicitly configure the multiplicity of each end, but I haven't found how to get the equivalent model using the fluent-api. When I do something like the following and generate a new db, the foreign key gets placed in table A instead of table B.
modelBuilder.Entity<A>().HasOptional(a => a.B).WithRequired(b => b.A);
我猜我需要使用一个约定,但是到目前为止,我一直无法获得所需的输出.
I'm guessing I need to use a convention, but so far I've been unable to get the desired output.
更新:
到目前为止,我找到的最接近的解决方案是使用以下代码在数据库中生成正确的SQL:
The closest solution I've found so far is to use the following which generates the correct SQL in the db:
modelBuilder.Entity<A>()
.HasOptional(a => a.B)
.WithOptionalDependent(b => b.A)
.Map(c => c.MapKey("BId"));
但是,它在概念上建模为0..1:0..1关系,但我还没有找到如何设置CASCADE删除规则来删除A时删除B的方法.
However, it's conceptually modeled as a 0..1:0..1 relationship and I haven't found how to set a CASCADE delete rule that deletes B when A is deleted.
推荐答案
我无法找到直接的解决方案,但是使用以下代码似乎可以满足我保留现有模式并创建具有以下特征的概念模型的要求:相同的多重性删除行为作为我的原始edmx模型.
I wasn't able to find a direct solution, but using the following code seems to meet my requirements of preserving the existing schema and creating a conceptual model that has the same multiplicities & delete behaviors as my original edmx model.
对于在后期处理IStoreModelConvention期间不需要更新概念模型的任何解决方案,我仍然会感兴趣.
I'd still be interested in any solutions that don't require updating the conceptual model during the post-processing IStoreModelConvention.
{
var overridesConvention = new OverrideAssociationsConvention();
modelBuilder.Conventions.Add(overridesConvention);
modelBuilder.Conventions.Add(new OverrideMultiplictyConvention(overridesConvention));
}
private class OverrideAssociationsConvention : IConceptualModelConvention<AssociationType>
{
...
public List<AssociationEndMember> MultiplicityOverrides { get; } = new List<AssociationEndMember>();
public void Apply(AssociationType item, DbModel model)
{
if (multiplicityOverrides.Contains(item.Name))
{
// Defer actually updating the multiplicity until the store model is generated
// so that foreign keys are placed in the desired tables.
MultiplicityOverrides.Add(item.AssociationEndMembers.Last());
}
if (cascadeOverrides.Contains(item.Name))
{
item.AssociationEndMembers.Last().DeleteBehavior = OperationAction.Cascade;
}
}
}
private class OverrideMultiplictyConvention : IStoreModelConvention<EdmModel>
{
private readonly OverrideAssociationsConvention overrides;
public OverrideMultiplictyConvention(OverrideAssociationsConvention overrides)
{
this.overrides = overrides;
}
public void Apply(EdmModel item, DbModel model)
{
overrides.MultiplicityOverrides.ForEach(o => o.RelationshipMultiplicity = RelationshipMultiplicity.One);
}
}
这篇关于EntityFramework:模型1:0..1与流利的api +约定的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!