如何使用导航属性和非标准密钥?

时间:2018-01-11 01:33:54

标签: c# entity-framework entity-framework-6 navigation-properties

假设我有以下数据库表,其中包含1:1映射

Table dbo.Foo with PrimaryKey FooRowId
Table dbo.Bar with PrimaryKey BarRowId

两个表都没有外键。

使用EF,我将模型定义如下。

建模Foo表

public class Foo
{
    [Key]
    public long FooRowId { get; set; }

    // Navigation
    public virtual Bar Bar { get; set; }
}

建模栏表

public class Bar
{
    [Key]
    public long BarRowId { get; set; }

    // Navigation
    public virtual Foo Foo { get; set; }
}

这给了我与导航属性相关的错误如下。

  

无法确定类型'MyOrg.Models.Foo'之间关联的主要结尾       和'MyOrg.Models.Bar'。这种关联的主要目的必须明确       使用关系流畅的API或数据注释进行配置。

解决方法之一是通过标准化属性名称,如下所示。

On Foo

public class Foo
{
    [Key]
    [Column("FooRowId")]
    public long FooId { get; set; }

    // Navigation
    public virtual Bar Bar { get; set; }
}

在栏上

public class Bar
{
    [Key]
    [Column("BarRowId")]
    public long BarId { get; set; }

    // Navigation
    public virtual Foo Foo { get; set; }
}

但是,要求声明我必须保留原始属性FooRowIDBarRowId。鉴于此约束,如何使导航属性有效?

1 个答案:

答案 0 :(得分:1)

尽管属性看起来很容易使用,但它限制了在其他数据库中重用类。

假设您已根据公司的标准(国家/地区)创建了类BillingAddress。您希望在两个不同的DbContexts中使用此类,每个DbContexts代表它们自己的数据库。数据库1中的BillingAddress在列" MyPrimaryKey"中具有主键,数据库2中的BillingAddress在列" Id"中具有主键。你无法使用属性来解决这个问题。

列和表的名称,表之间的关系是数据库的一部分。因此,这应该在DbContext中描述。如果您不在DbSet类中使用Attributes,那么您将能够在不同的数据库中使用相同的类。

所以让我们用流利的Api写你的桌面设计

请参阅:

下面我举例说明所有三个类别:

  • 配置表名称和表格的主键
  • 配置其中一个属性:列名称
  • 配置表之间的关系,例如一对多

请记住:如果您首先使用代码,并坚持the entity framework code first conventions,则不需要这些代码。只要你坚持这些约定,Entity Framework就能非常有能力检测主键,外键,表之间的关系。

但是如果你的表不同,你的DbContext中需要以下流畅的API

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     // Configure entity table FOO:
     var entityFoo = modelBuilder.Entity<Foo>();

     // example: configure Name and primary key of foo table
     entityFoo.ToTable("MySpecialFooTable");
     entifyFoo.HasKey(foo => foo.FooRowId);

     // example: configure property Name is in column FooName:
     entityFoo.Property(foo => foo.Name).HasColumnName("MyFooName");

     // example: one-to-many relation between foo and bar
     // every Foo has zero or more Bars in property MyBars,
     // every Bar belongs to exactly one For in property MyFoo
     // using foreign key MyFooId:
     entityFoo.HasMany(foo => foo.MyBars)         // Foo has zero or more Bars in MyBars
              .WithRequired(bar => bar.MyFoo)     // every Bar belongs to one Foo
              .HasForeignKey(bar => bar.MyFooId); // using foreign key MyFooId
}