2013-10-15 56 views
1

我试图让1到0..1的映射在实体框架代码中工作首先,但不断收到错误: ReferentialConstraint中的依赖属性是映射到商店生成的列。专栏:'Id'。在实体框架代码中映射1到0..1首先

我有一个MainLocation与所需的位置,但由于位置可以有多个子位置,位置对象中不需要MainLocation。

MainLocation与MainLocationAddress具有类似的关系,但这是一个1对1的关系,它依次组成相同的数据库表。

ER模型应该是这样的: enter image description here

我的实体是这样的:

[Table("MainLocation")] 
public class MainLocation : IEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    [Required] 
    public virtual MainLocationAddress Address { get; set; } 
    [Required] 
    public virtual Location Location { get; set; } 
} 

[Table("MainLocation")] 
public class MainLocationAddress : BaseAddress 
{ 
    [Key, ForeignKey("MainLocation")] 
    [DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public int Id { get; set; } 
    public virtual MainLocation MainLocation { get; set; } 
} 

public class Location : IEntity 
{ 
    public int Id { get; set; } 
    public virtual Location ParentLocation { get; set; } 
    public virtual ICollection<Location> ChildLocations { get; set; } 
    protected virtual MainLocation MainLocation { get; set; } 
    internal MainLocation GetMainLocation() { return this.MainLocation; } 
    internal void SetMainLocation(MainLocation mainLocation) { MainLocation = mainLocation; } 
} 

我在我的DbContext类配置OnModelCreating消协:

modelBuilder.Entity<MainLocation>() 
      .HasRequired(x => x.Location) 
      .WithOptional(); 

modelBuilder.Entity<MainLocation>() 
      .HasRequired(x => x.Address) 
      .WithRequiredPrincipal(); 

PS!位置上的MainLocation属性受到保护,因为它不应该直接访问。相反,我有一个服务层,它从位置获取值或从ParentLocation继承的值。我试图将其更改为公开,以查看它是否对我收到的错误进行了更改。

尽管我可以将.WithOptional()扩展为.WithOptional(x => x.MainLocation),但在声明的错误中仍然没有任何更改。

回答

0

我已经认识到,这是不可能在EF中完成,因为它是目前(1到0..1协会)。

我已经解决了它在我们的解决方案中让所有的孩子的位置有一个参考的主要位置。我仍然可以通过查找没有父母位置的地点来获得顶级组织。所以,虽然它不是我们想要的,但它并没有打破我们的商业模式。

1

我已经实现了两个实体Person和User之间的1:0-1关联。要求,用户必须有一个且只有一个人;而一个人可能会或可能不会与用户关联。

public class Person 
{ 
    public int PersonId { get; set; } 
    public virtual User User { get; set; } 
} 

public class User 
{ 
    public int UserId { get; set; } 
    public int PersonId { get; set; } 
    public virtual Person Person { get; set; } 
} 

如下定义EntityTypeConfiguration类,并将它们包含在DbContext的OnModelCreating方法中。

public class PersonConfiguration : EntityTypeConfiguration<Person> 
{ 
    public PersonConfiguration() 
    { 
     ToTable("People"); 
     HasKey(p => p.PersonId); 
     Property(p => p.PersonId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     HasOptional(p => p.User).WithRequired(u => u.Person); // User is option here but 
                   // Person is required in User 
    } 

} 

public class UserConfiguration : EntityTypeConfiguration<User> 
{ 
    public UserConfiguration() 
    { 

     ToTable("Users"); 
     HasKey(u => u.UserId); 
     Property(u => u.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     // Create a unique index in the Users table on PersonId 
     Property(u => u.PersonId).IsRequired().HasColumnAnnotation("Index", 
      new IndexAnnotation(new IndexAttribute("IX_PersonId") { IsUnique = true })); 

    } 

} 

将下列行放在DbContext.OnModelCreating方法中。

 modelBuilder.Configurations.Add(new PersonConfiguration()); 
     modelBuilder.Configurations.Add(new UserConfiguration()); 

运行Add-Migration命令,您将在DbMigration,Up方法中获得类似于以下内容的内容。进行如下更改。

 CreateTable(
      "dbo.Users", 
      c => new 
       { 
        Id = c.String(nullable: false, maxLength: 128), 
        PersonId = c.Int(nullable: false), 
        Person_PersonId = c.Int(nullable: false), // Delete this 
       }) 
      .PrimaryKey(t => t.Id) 
      .ForeignKey("dbo.People", t => t.Person_PersonId) // change to .ForeignKey("dbo.People", t => t.PersonId) 
      .Index(t => t.PersonId, unique: true) // append a ';' 
      .Index(t => t._Person_PersonId); // Delete this 

     CreateTable(
      "dbo.People", 
      c => new 
       { 
        PersonId = c.Int(nullable: false, identity: true), 
       }) 
      .PrimaryKey(t => t.PersonId) 

修改Down()方法如下。

变化

DropForeignKey("dbo.Users", "Person_PersonId", "dbo.People"); 

DropForeignKey("dbo.AppUsers", "PersonId", "dbo.People"); 

变化

DropIndex("dbo.AppUsers", new[] { "Person_PersonId" }); 

DropIndex("dbo.AppUsers", new[] { "PersonId" }); 

运行以此迁移为目标的Update-Database命令。生成的用户和人员表将在PersonId外键上具有一对一关联。

0

此方案适用于更新数据库,因为所需的数据库结构显示了用户和人员表之间的一对一关系。但是,由于某些原因试图查询用户表。

我通过删除PersonId属性来更改User类。

public class User 
{ 
    public int UserId { get; set; } 
    public virtual Person Person { get; set; } 
} 

的UserConfiguration类变为:

public class UserConfiguration : EntityTypeConfiguration<User> 
{ 
    public UserConfiguration() 
    { 

     ToTable("Users"); 
     HasKey(u => u.UserId); 
     Property(u => u.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

    } 

} 

的加载迁移生产: CREATETABLE( “dbo.Users”, C =>新 { 编号= c.String(可为空的:假的,最大长度:128), Person_PersonId = c.Int(可为空的:假),//保持此 }) .PrimaryKey(T => t.UserId) .ForeignKey(“d bo.People“,t => t.Person_PersonId) .Index(t => t._Person_PersonId); //改为.Index(t => t._Person_PersonId,unique:true);

更新数据库生成具有一对一关系的用户和人员表,并且该框架使用其自己生成的Person_PersonId列。