Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework EF Code First 4.1-如何配置与默认值的一对多关系_Entity Framework_Entity_Ef Code First_Fluent Interface - Fatal编程技术网

Entity framework EF Code First 4.1-如何配置与默认值的一对多关系

Entity framework EF Code First 4.1-如何配置与默认值的一对多关系,entity-framework,entity,ef-code-first,fluent-interface,Entity Framework,Entity,Ef Code First,Fluent Interface,我有一个客户实体,它引用一组地址。这里的复杂之处在于,我希望能够将特定地址识别为默认地址 如果可能,我希望在Customer表中保留默认地址的FK。这似乎比在addresses表中有一列来标识默认值更优雅 在定义这种关系方面,我对fluentapi有困难。当我运行以下代码时,我得到一个异常,它说: “保存未公开其关系的外键属性的实体时出错。EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。请参阅有关详细信息,

我有一个客户实体,它引用一组地址。这里的复杂之处在于,我希望能够将特定地址识别为默认地址

如果可能,我希望在Customer表中保留默认地址的FK。这似乎比在addresses表中有一列来标识默认值更优雅

在定义这种关系方面,我对fluentapi有困难。当我运行以下代码时,我得到一个异常,它说: “保存未公开其关系的外键属性的实体时出错。EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。请参阅有关详细信息,请参阅InnerException。“ 无法确定依赖操作的有效顺序。依赖项可能由于外键约束、模型要求或存储生成的值而存在

我创建了一个控制台应用程序来显示确切的问题。在这个测试应用程序中,我有一个客户实体、一个地址和flient 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();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Data.Entity.ModelConfiguration;
使用System.ComponentModel.DataAnnotations;
使用System.Data.Entity;
命名空间OneToManyWithDefault
{
公共类客户
{
专用ICollection m_地址;
公众客户()
{
地址=新列表();
}
公共int Id{get;set;}
公共字符串CompanyName{get;set;}
公共虚拟ICollection地址
{
得到
{
if(m_地址==null)
{
m_地址=新列表();
}
返回m_地址;
}
设置
{
m_地址=值;
}
}
公共地址默认地址{get;set;}
public int DefaultAddressId{get;set;}
}
公共课堂演讲
{
公共int Id{get;set;}
公共字符串{get;set;}
公共客户客户{get;set;}
}
公共类MyContext
:DbContext
{
公共数据库集客户{get;set;}
公共MyContext(字符串连接字符串)
:基本(连接字符串)
{
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(新CustomerConfiguration());
添加(新地址配置());
基于模型创建(modelBuilder);
}
}
公共类CustomerConfiguration
:EntityTypeConfiguration
{
公共客户配置()
:base()
{
HasKey(p=>p.Id);
属性(p=>p.Id)
.HasColumnName(“Id”)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
属性(p=>p.CompanyName)
.HasColumnName(“名称”)
.IsRequired();
//配置默认地址的映射(这可能是错误的!):
HasRequired(p=>p.DefaultAddress)。WithMany()
.Map(x=>x.MapKey(“DefaultAddressId”))
.WillCascadeOnDelete(假);
HasRequired(p=>p.DefaultAddress)
.有很多
.HasForeignKey(x=>x.DefaultAddressId);
ToTable(“客户”);
}
}
公共类地址配置
:EntityTypeConfiguration
{
公共地址配置()
:base()
{
HasKey(p=>p.Id);
属性(p=>p.Id)
.HasColumnName(“Id”)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
地产(p=>p.Town)
.HasName(“城镇”)
.IsRequired();
需要(p=>p.Customer)
.具有多个(c=>c地址)
.Map(x=>x.MapKey(“CustomerId”);
ToTable(“地址”);
}
}
班级计划
{
私有常量字符串连接字符串=
@“服务器=。\sql2005;数据库=OneToManyWithDefault;集成安全性=SSPI;”;
静态void Main(字符串[]参数)
{
客户总部=新客户();
headOffice.CompanyName=“C1”;
地址=新地址();
地址:Town=“Colchester”;
总部。地址。添加(地址);
地址=新地址();
地址:Town=“Norwich”;
总部。地址。添加(地址);
headOffice.DefaultAddress=地址;
MyContext上下文=新的MyContext(ConnectionString);
context.Customers.Add(总部);
SaveChanges();
控制台。WriteLine(“完成”);
Console.ReadLine();
}
}
}
非常感谢,


Paul.

我不明白EF在例外情况下谈论的“未公开外键”是什么。我认为内部例外是重要的部分:

无法确定有效的订购 对于依赖操作。依赖关系 可能由于外键而存在 约束、模型需求或 存储生成的值

我认为您模型中的问题在于
客户
地址
之间存在相互依赖关系:一个地址需要一个客户(您在映射代码中将其标记为必需),另一方面,客户需要一个地址(默认地址为必需
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 { ... } set { ... } }
    public Address DefaultAddress { get; set; }
    public int? DefaultAddressId { get; set; } // FK for optional relationship
}

public class Address
{
    public int Id { get; set; }
    public string Town { get; set; }
    public Customer Customer { get; set; }
}

// ...

public class CustomerConfiguration : EntityTypeConfiguration<Customer>
{
    public CustomerConfiguration() : base()
    {
        Property(p => p.CompanyName)
            .HasColumnName("Name")
            .IsRequired();

        HasMany(c => c.Addresses)
            .WithRequired(a => a.Customer)
            .Map(x => x.MapKey("CustomerId"));
    }
}

public class AddressConfiguration : EntityTypeConfiguration<Address>
{
    public AddressConfiguration() : base()
    {
        Property(p => p.Town)
            .HasColumnName("Town")
            .IsRequired();
    }
}
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;
    //We don't set the default address here as SaveChanges would throw an
    //exception. But because it is optional now we are allowed to leave it null.

    MyContext context = new MyContext(ConnectionString);
    context.Customers.Add(headOffice);
    context.SaveChanges();

    headOffice.DefaultAddress = address; // headoffice and address have now PKs
    context.SaveChanges(); // Updates headoffice in the DB with default address
}