2016-11-15 47 views
1

我有从EDMX模型生成以下类:的EntityFramework:模式1:0..1用流利的API +公约的关系

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.编号为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模型,我可以明确地配置各端的多重性,但我还没有找到如何使用流畅的API来获取等效模型。当我这样做以下,并生成一个新的数据库,外键被放在表A,而不是表B.

modelBuilder.Entity<A>().HasOptional(a => a.B).WithRequired(b => b.A); 

我猜我需要使用惯例,但到目前为止,我已经无法获得所需的输出。

UPDATE:

我到目前为止发现的最接近解决方案是使用产生的分贝正确的SQL如下:

modelBuilder.Entity<A>() 
    .HasOptional(a => a.B) 
    .WithOptionalDependent(b => b.A) 
    .Map(c => c.MapKey("BId")); 

然而,它的概念建模为0 .1:0..1关系,并且我还没有找到如何设置删除A时删除B的CASCADE删除规则。

+0

EF不支持这种双向关系。欲了解更多信息,请参阅[EF代码优先:第5部分 - 一对一外键关联中的关联](https://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first部分5一对一的外键关联) –

+0

@IvanStoev就我所知,使用数据库优先+ edmx建模没有任何问题。我只是试图切换到数据库第一+代码而不修改现有(工作)数据库架构和生成的类。这两种情况都引用了EntityFramework.dll和EntityFramework.SqlServer.dll,对吧? edmx建模是否使用非公共功能来启用模型定制? – kayle

+0

AFAIK有一些Code First不支持的edmx特性,不能说这是否是其中之一。我所能说的从我的经验来看,所有来自联系的系列都适用。 –

回答

0

我无法找到直接的解决方案,但使用下面的代码似乎满足我保留现有模式和创建一个概念模型的要求,该模型与我的原始edmx模型具有相同的多重性&删除行为。

我仍然对在后处理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); 
     } 
    }