3

我在 VS2012 中使用 MVC4,并且我正在遵循一个 table-per-type 继承方法。我正在尝试使用该Seed()方法将数据添加到我的数据库中。

我有以下课程:

房东

[Table("Landlord")]
public class Landlord : UserProfile
{
    // A Landlord can have many ResidentialProperties
    [ForeignKey("ResidentialPropertyId")]
    public virtual ICollection<ResidentialProperty> ResidentialProperties { get; set; }
}

住宅物业

[Table("ResidentialProperty")]
public class ResidentialProperty
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ResidentialPropertyId { get; set; }

    // A ResidentialProperty has 1 Landlord
    public virtual int UserId { get; set; }
    public virtual UserProfile UserProfile { get; set; } 

}

所以Landlord继承自UserProfile,因此没有 PK 属性Landlord.

我试图实现的关系如下:

  • ALandlord可以有很多ResidentialProperties(1:n)
  • 一个ResidentialProperty罐子(在应用程序的范围内)有一个Landlord(1:1)

我认为我配置模型的方式足以update-database成功地从包管理器运行命令,并将我的Seed()方法中的内容添加到我的数据库中。事实并非如此,我收到以下错误:

无法确定“LetLord.Models.ResidentialProperty_UserProfile”关系的主体端。多个添加的实体可能具有相同的主键。

在阅读之后,我意识到我想要创建的关系需要使用 Fluent API 来实现,所以我尝试了以下方法:

        modelBuilder.Entity<Landlord>()
            .HasMany(x => x.ResidentialProperties)
            .WithOptional()
            .HasForeignKey(x => x.ResidentialPropertyId);

        modelBuilder.Entity<ResidentialProperty>()
            .HasRequired(x => x.UserProfile);

当我尝试update-database通过包管理器执行命令时,出现以下错误:

\tSystem.Data.Entity.Edm.EdmAssociationEnd: : 多重性在关系“Landlord_ResidentialProperties”中的角色“Landlord_ResidentialProperties_Target”中无效。因为从属角色指的是关键属性,所以从属角色的多重性的上限必须是“1”。

我完全不知道如何解决我的问题。我在这上面花了很多时间,这非常令人沮丧,因为我觉得它应该很容易完成。如果有人有解决方案,如果您能与我分享,我将不胜感激。

编辑- 上述第一个错误引发的异常输出:

System.Data.Entity.Infrastructure.DbUpdateException:无法确定“LetLord.Models.ResidentialProperty_Landlord”关系的主体端。多个添加的实体可能具有相同的主键。---> System.Data.UpdateException:无法确定“LetLord.Models.ResidentialProperty_Landlord”关系的主体端。多个添加的实体可能具有相同的主键。在 System.Data.Mapping.Update.Internal.UpdateTranslator.RegisterEntityReferentialConstraints(IEntityStateEntry stateEntry, Boolean currentValues) 在 System.Data.Mapping.Update.Internal.UpdateTranslator.RegisterReferentialConstraints(IEntityStateEntry stateEntry) 在 System.Data.Mapping.Update.Internal。 UpdateTranslator.PullModifiedEntriesFromStateManager() 在 System.Data.Mapping.Update.Internal.UpdateTranslator。

编辑- 解决方案:

实体应该按照下面拉迪斯拉夫的回答,我的错误是在基类的多方面而不是派生类上创建导航属性。

Seed()我的下一个错误是在我的方法中对实体进行排序。我在下面添加了它们应该是什么样的,这尤其适用于添加具有关联的实体时。

    protected override void Seed(LetLord.Models.LetLordContext context)
    {

        try
        {

            #region Landlords

            // create a list of landlords first - a landlord can have many residential properties, make this  = new List<ResidentialProperty>()
            var landlords = new List<Landlord>
        {
            // landlord 1
            new Landlord { UserName="Frank",     FirstName="Frank",   LastName="O'Sullivan", Email="a@a.com", AccountType=(int)AccountType.Landlord, ResidentialProperties = new List<ResidentialProperty>() }

            // ...
        };
            landlords.ForEach(l => context.UserProfile.AddOrUpdate(l));
            context.SaveChanges();

            #endregion

            #region ResidentialProperties

            // then create a list of properties
            var residentialProperties = new List<ResidentialProperty>
        {
            // Property 1 associated with LandLord 1
            new ResidentialProperty { PropTypeValue=(int)PropertyType.Detached, Description="Some description...", NumberOfBedrooms="4", NumberOfReceptionRooms="2", NumberOfBathrooms="2", HasBackGarden=true, HasFrontGarden=true, HasSecureParking=false, IsDisabledFriendly=false, DateAdded=DateTime.Now, Landlord = landlords.FirstOrDefault(u => u.UserId == 11) } // in my case, user 11 is landlord 1

            // ... 
        };
            residentialProperties.ForEach(rp => context.ResidentialProperty.AddOrUpdate(rp));
            context.SaveChanges(); 

            #endregion

            // then add our list of properties to our list of landlords
            landlords[0].ResidentialProperties.Add(residentialProperties[0]);
            landlords[1].ResidentialProperties.Add(residentialProperties[1]);
            landlords[2].ResidentialProperties.Add(residentialProperties[2]);
            landlords[3].ResidentialProperties.Add(residentialProperties[3]);
            landlords[4].ResidentialProperties.Add(residentialProperties[4]);
            landlords[5].ResidentialProperties.Add(residentialProperties[5]);
            landlords[6].ResidentialProperties.Add(residentialProperties[6]);
            landlords[7].ResidentialProperties.Add(residentialProperties[7]);
            landlords[8].ResidentialProperties.Add(residentialProperties[8]);
            landlords[9].ResidentialProperties.Add(residentialProperties[9]);
            context.SaveChanges();

        }
        catch (Exception ex)
        {
            string lines = ex.ToString();
            System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Users\Home\Desktop\error.txt");
            file.WriteLine(lines);
            file.Close();
        }

当我在修复上述代码后尝试运行时update-database,遇到了这个错误:

System.Data.Entity.Infrastructure.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> System.Data.UpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> System.Data.SqlClient.SqlException:INSERT 语句与 FOREIGN KEY 约束“FK_dbo.ResidentialProperty_dbo.Landlord_UserId”冲突。冲突发生在数据库“C:\USERS\HOME\DESKTOP\LETLORD\LETLORD\APP_DATA\LETLORD.MDF”、表“dbo.Landlord”、列“UserId”中。该语句已终止。

经过快速搜索后,我发现(我认为)导致了这个错误,因为我的数据库中已经有数据。删除并重新创建数据库解决了这个问题,当我Seed()再次运行该方法时,数据已成功添加。

4

1 回答 1

3

如果房东可以有多个房产并且房产可以有多个房东,那么模型应该如下所示:

[Table("Landlord")]
public class Landlord : UserProfile
{
    // A Landlord can have many ResidentialProperties
    public virtual ICollection<ResidentialProperty> ResidentialProperties { get; set; }
}

[Table("ResidentialProperty")]
public class ResidentialProperty
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ResidentialPropertyId { get; set; }

    // A ResidentialProperty has 1 Landlord
    // Foreign key is on many side and it contains value of primary key on one side
    // In your case FK must contain value of property's landlord
    public virtual int UserId { get; set; }
    // ForeignKey attribute pairs navigation property on many side with foreign key propety 
    [ForeignKey("UserId")]
    public virtual Landlord Landlord { get; set; } 
}
于 2013-02-18T20:03:23.937 回答