我想使用自有类型进行TableSplitting。我有以下型号:
public class Account
{
public GUID Id { get; set; }
public string Email { get; set; }
public StreetAddress Address { get; set; }
}
public class StreetAddress
{
public string Name { get; set; }
public string Address { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public Location Location { get; set; }
}
public class Location
{
public double Lat { get; set; }
public double Lng { get; set; }
}
我定义了这样的帐户映射:
public override void Map(EntityTypeBuilder<Account> map)
{
// Keys
map.HasKey(x => x.Id);
// Indexs
map.HasIndex(x => x.Email).IsUnique();
// Property mappings.
map.Property(x => x.Email).HasMaxLength(255).IsRequired();
// Owned types.
map.OwnsOne(x => x.Address, cb => cb.OwnsOne(a => a.Location));
}
当我运行迁移时,工作正常,并且在数据库中创建了列。但是当我尝试插入并保存这样的地址时:
var account1 = new Account("e@mail.com", "First", "Last")
{
Address = new StreetAddress()
{
Address1 = "Street 1",
City = "City",
Zipcode = "2000",
Country = "Denmark",
Location = new Location()
{
Lat = 0.0,
Lng = 5.5
}
}
};
this.Context.Accounts.Add(account1);
我收到此错误
消息“'帐户'的实体正在共享”帐户“表 'Account.Address#StreetAddress',但没有此类型的实体 具有相同的键值'Id:b7662057-44c2-4f3f-2cf0-08d504db1849'那个 已标记为“已添加”。“
答案 0 :(得分:0)
您必须添加构造函数并初始化拥有的实体。
public class Account
{
public Account (){
Address = new StreetAddress();
}
public GUID Id { get; set; }
public string Email { get; set; }
public StreetAddress Address { get; set; }
}
public class StreetAddress
{
public StreetAddress(){
Location = new Location();
}
public string Name { get; set; }
public string Address { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public Location Location { get; set; }
}
public class Location
{
public double Lat { get; set; }
public double Lng { get; set; }
}
换句话说,不能有可选的拥有实体。
注意:如果您有一个非空的构造函数,由于ef core limitations.
,还必须添加一个空的构造函数答案 1 :(得分:0)
public class Account {
public GUID Id { get; set; }
public string Email { get; set; }
public StreetAddress Address { get; set; }
}
public class StreetAddress {
public string Name { get; set; }
public string Address { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public Location[] Location { get; set; }
public class Location {
public double Lat { get; set; }
public double Lng { get; set; }
}
尝试此操作是因为一旦您以所有形式调用对象都与Account类有关,但现实情况是您没有定义我建立的那种关系
答案 2 :(得分:0)
对于要添加到数据库中的帐户。它的引用应该首先保存在表中。要在数据库中添加数据,它应该按以下顺序:位置 > 街道地址 > 帐户
答案 3 :(得分:0)
我敢肯定,如果您尝试将每个对象添加到上下文中,然后构建它会起作用的父对象 意思是先添加位置,然后创建地址并引用您创建的位置对象 将地址添加到上下文中 然后创建帐户并引用其中添加的地址!
或者你可以在你的模型中添加构造器来初始化每个导航属性的新实例
最后一件事,这真的不应该成为 EF Core 5 的问题,因为它在导航属性方面有很多新的花里胡哨
public override void Map(EntityTypeBuilder<Account> map)
{
// Keys
map.HasKey(x => x.Id);
// Indexs
map.HasIndex(x => x.Email).IsUnique();
// Property mappings.
map.Property(x => x.Email).HasMaxLength(255).IsRequired();
// Owned types.
map.OwnsOne(x => x.Address, cb => cb.OwnsOne(a => a.Location));
}
如果你正在使用它,你真的不需要下面的部分
只需适当添加您的 DbSet<T>
即可
答案 4 :(得分:0)
考虑使用虚拟属性。这也可以用于在您的应用程序中进行延迟加载
public class Account
{
public GUID Id { get; set; }
public string Email { get; set; }
public virtual StreetAddress Address { get; set; }
}
public class StreetAddress
{
public string Name { get; set; }
public string Address { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public virtual Location Location { get; set; }
}
public class Location
{
public double Lat { get; set; }
public double Lng { get; set; }
}