我在 VS2012 中使用 MVC4,并且我遵循一种表类型继承方法。我正在尝试使用 Seed()
方法将数据添加到我的数据库。
我有以下类(class):
房东
[Table("Landlord")]
public class Landlord : UserProfile
{
// A Landlord can have many ResidentialProperties
[ForeignKey("ResidentialPropertyId")]
public virtual ICollection<ResidentialProperty> ResidentialProperties { get; set; }
}
住宅属性(property)
[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
,因此Landlord中没有PK属性。
我要实现的关系如下:
- 一个
房东
可以拥有多个ResidentialProperties
(1:n) ResidentialProperty
可以(在应用程序的范围内)有一个Landlord
(1:1)
我认为我配置模型的方式足以从包管理器成功运行 update-database
命令,并添加我的 Seed()
我的数据库的方法。事实并非如此,我收到以下错误:
Unable to determine the principal end of the 'LetLord.Models.ResidentialProperty_UserProfile' relationship. Multiple added entities may have the same primary key.
在阅读之后我意识到我想要创建的关系需要使用 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: : Multiplicity is not valid in Role 'Landlord_ResidentialProperties_Target' in relationship 'Landlord_ResidentialProperties'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be '1'.
我完全不知道如何解决我的问题。我花了很多时间在这上面,这很令人沮丧,因为我觉得这应该很容易完成。如果有人有解决方案,请与我分享,我将不胜感激。
编辑 - 上述第一个错误抛出的异常输出:
System.Data.Entity.Infrastructure.DbUpdateException: Unable to determine the principal end of the 'LetLord.Models.ResidentialProperty_Landlord' relationship. Multiple added entities may have the same primary key. ---> System.Data.UpdateException: Unable to determine the principal end of the 'LetLord.Models.ResidentialProperty_Landlord' relationship. Multiple added entities may have the same primary key. at System.Data.Mapping.Update.Internal.UpdateTranslator.RegisterEntityReferentialConstraints(IEntityStateEntry stateEntry, Boolean currentValues) at System.Data.Mapping.Update.Internal.UpdateTranslator.RegisterReferentialConstraints(IEntityStateEntry stateEntry) at System.Data.Mapping.Update.Internal.UpdateTranslator.PullModifiedEntriesFromStateManager() at System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands() at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache) at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) at System.Data.Entity.Internal.InternalContext.SaveChanges() --- End of inner exception stack trace --- at System.Data.Entity.Internal.InternalContext.SaveChanges() at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() at System.Data.Entity.DbContext.SaveChanges() at LetLord.Migrations.Configuration.Seed(LetLordContext context) in c:\Users\Home\Desktop\LetLord\LetLord\Migrations\Configuration.cs:line 83
编辑 - 解决方案:
实体应该按照下面 Ladislav 的回答,我的错误是在基类的多边设置导航属性,而不是派生类。
我的下一个错误是在我的 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: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ResidentialProperty_dbo.Landlord_UserId". The conflict occurred in database "C:\USERS\HOME\DESKTOP\LETLORD\LETLORD\APP_DATA\LETLORD.MDF", table "dbo.Landlord", column 'UserId'. The statement has been terminated.
快速搜索后,我发现这个错误是(我认为)造成的,因为我的数据库中已经有数据。删除并重新创建数据库解决了这个问题,当我再次运行 Seed()
方法时,数据已成功添加。
最佳答案
如果房东可以有多个属性并且属性可以有多个一个房东模型应该是这样的:
[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; }
}
关于c# - Entity Framework/code first/table-per-type inheritance——实现派生类和具体类之间的一对多关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14940907/