我有一个客户实体引用一组地址。这里的复杂之处在于我希望能够识别特定地址作为默认地址。EF Code First 4.1 - 如何配置默认的一对多关系
如果可能,我想在客户表中保存默认地址的FK。这似乎比在地址表中使用列来标识默认值更为优雅。
我在定义这种关系方面遇到了流畅的API问题。当我运行下面的代码时,我得到一个异常,它说: “保存不会为其关系公开外键属性的实体时发生错误。EntityEntries属性将返回null,因为无法将单个实体标识为例外情况:通过在实体类型中公开外键属性,可以更轻松地处理保存时的异常,详情请参阅InnerException。 “无法确定依赖操作的有效排序。由于外键约束,模型要求或存储生成的值,可能存在依赖关系。”
我创建了一个控制台应用程序来显示确切的问题。在这个测试应用程序中,我有一个Customer实体,一个Address和api api配置。
任何帮助将非常感激:
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
namespace OneToManyWithDefault
{
public class Customer
{
private ICollection<Address> m_Addresses;
public Customer()
{
Addresses = new List<Address>();
}
public int Id { get; set; }
public string CompanyName { get; set; }
public virtual ICollection<Address> Addresses
{
get
{
if (m_Addresses == null)
{
m_Addresses = new List<Address>();
}
return m_Addresses;
}
set
{
m_Addresses = value;
}
}
public Address DefaultAddress { get; set; }
public int DefaultAddressId { get; set; }
}
public class Address
{
public int Id { get; set; }
public string Town { get; set; }
public Customer Customer { get; set; }
}
public class MyContext
: DbContext
{
public DbSet<Customer> Customers { get; set; }
public MyContext(string connectionString)
: base(connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CustomerConfiguration());
modelBuilder.Configurations.Add(new AddressConfiguration());
base.OnModelCreating(modelBuilder);
}
}
public class CustomerConfiguration
: EntityTypeConfiguration<Customer>
{
public CustomerConfiguration()
: base()
{
HasKey(p => p.Id);
Property(p => p.Id)
.HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
Property(p => p.CompanyName)
.HasColumnName("Name")
.IsRequired();
// Configure the mapping for the Default Address (this is likely to be wrong!):
HasRequired(p => p.DefaultAddress).WithMany()
.Map(x => x.MapKey("DefaultAddressId"))
.WillCascadeOnDelete(false);
HasRequired(p => p.DefaultAddress)
.WithMany()
.HasForeignKey(x => x.DefaultAddressId);
ToTable("Customers");
}
}
public class AddressConfiguration
: EntityTypeConfiguration<Address>
{
public AddressConfiguration()
: base()
{
HasKey(p => p.Id);
Property(p => p.Id)
.HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
Property(p => p.Town)
.HasColumnName("Town")
.IsRequired();
HasRequired(p => p.Customer)
.WithMany(c => c.Addresses)
.Map(x => x.MapKey("CustomerId"));
ToTable("Addresses");
}
}
class Program
{
private const string ConnectionString =
@"Server=.\sql2005;Database=OneToManyWithDefault;integrated security=SSPI;";
static void Main(string[] args)
{
Customer headOffice = new Customer();
headOffice.CompanyName = "C1";
Address address = new Address();
address.Town = "Colchester";
headOffice.Addresses.Add(address);
address = new Address();
address.Town = "Norwich";
headOffice.Addresses.Add(address);
headOffice.DefaultAddress = address;
MyContext context = new MyContext(ConnectionString);
context.Customers.Add(headOffice);
context.SaveChanges();
Console.WriteLine("Done.");
Console.ReadLine();
}
}
}
非常感谢,
保罗。
谢谢你,这是有道理的,你在这里说。我会试试这个,并在这里更新我如何继续。 – P2l 2011-05-10 09:32:48
我现在已经测试过了,它适用于我们。正如你所说,它很丑,但我看不到另一种方法。谢谢你的帮助。 – P2l 2011-05-12 12:55:49