1

我试图让 1 到 0..1 映射以在 Entity Framework Code First 中工作,但不断收到错误: ReferentialConstraint 中的依赖属性被映射到存储生成的列。列:'Id'。

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

MainLocation 与 MainLocationAddress 具有类似的关系,但这是一个 1 对 1 的关系,它又构成了相同的 db 表。

ER 模型应如下所示: 在此处输入图像描述

我的实体如下所示:

[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!Location 上的 MainLocation 属性受到保护,因为不应直接访问它。相反,我有一个服务层,它从位置获取值或从父位置获取继承值。我试图将其更改为公开,以查看它是否对我遇到的错误进行了任何更改。

尽管我能够将 .WithOptional() 扩展到 .WithOptional(x => x.MainLocation),但所述错误仍然没有变化。

4

3 回答 3

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 命令。生成的 Users 和 People 表将在 PersonId 外键上具有一对一的关联。

于 2014-07-25T20:12:43.787 回答
0

此方案在 Update-Database 上运行良好,因为所需的数据库结构显示了 User 和 People 表之间的一对一关系。但是,由于某种原因尝试查询用户表。

我通过删除 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);

     }

}

Add-Migration 产生: CreateTable( "dbo.Users", c => new { Id = c.String(nullable: false, maxLength: 128), Person_PersonId = c.Int(nullable: false), // 保留这个 } ) .PrimaryKey(t => t.UserId) .ForeignKey("dbo.People", t => t.Person_PersonId) .Index(t => t._Person_PersonId); // 更改为 .Index(t => t._Person_PersonId, unique: true);

Update-Database 生成具有一对一关系的 User 和 People 表,并且框架使用自己生成的 Person_PersonId 列。

于 2014-07-27T00:52:37.803 回答
0

我开始意识到这在 EF 中是不可能实现的,因为目前(1 到 0..1 关联)。

我在我们的解决方案中通过让所有子位置都引用主位置来解决它。我仍然可以通过寻找没有父位置的位置来获得顶级组织。所以,虽然这不是我们想要的,但它不会破坏我们的商业模式。

于 2013-10-16T06:46:51.310 回答