【问题标题】:Pocos - The relationship could not be changed because one or more of the foreign-key properties is non-nullablePocos - 无法更改关系,因为一个或多个外键属性不可为空
【发布时间】:2014-04-26 13:06:36
【问题描述】:

我有三个表,它们是 user、user_details 和 user_acls。用户表是主表,另外两个是子表,存储与用户相关的信息。后两个表的外键是user_id,user_id是user表的主键。

使用实体框架和 pocos 我已经设置了以下类结构,我只会为我的一个子表执行此操作,因为一旦我解决了这个问题,我应该能够将相同的逻辑应用于我的另一个用户表.

用户类

namespace myclass.Core.Domain.Customers
{

    public partial class User : BaseEntity
    {
        private ICollection<UsersSitesAcl> _usersSitesAcls;
        private ICollection<CompaniesAcl> _companiesAcls;
        private ICollection<UserDetails> _userDetails;

        public virtual Guid userguid { get; set; }
        public virtual string first_name { get; set; }
        public virtual string last_name { get; set; }
        public virtual string email_address { get; set; }
        public virtual System.DateTime? activated_date { get; set; }
        public virtual string pwrd { get; set; }
        public virtual string loginname { get; set; }
        public virtual string title { get; set; }
        public virtual string suffix { get; set; }
        public virtual string secretquestion { get; set; }
        public virtual string secretanswer { get; set; }
        public virtual long? birthyear { get; set; }
        public virtual string last_four_ssn { get; set; }
        public virtual bool? suspended_yn { get; set; }
        public virtual string account_status { get; set; }



        public virtual ICollection<UsersSitesAcl> usersSitesAcls
        {
            get
            {
                var sitesAcls = new List<UsersSitesAcl>();
                if (_usersSitesAcls != null)
                {
                    var query = from usa in _usersSitesAcls
                                where usa.active_yn
                                select usa;

                    sitesAcls = query.ToList();
                }
                return sitesAcls;
            }
            protected set { _usersSitesAcls = value; }
        }

        public virtual ICollection<CompaniesAcl> companiesAcls
        {
            get
            {
                var companyAcls = new List<CompaniesAcl>();
                if (_companiesAcls != null)
                {
                    var query = from ca in _companiesAcls
                                where ca.active_yn
                                select ca;

                    companyAcls = query.ToList();
                }
                return companyAcls;
            }
            protected set { _companiesAcls = value; }
        }


        public virtual ICollection<UserDetails> userDetails
        {
            get
            {
                var userDetails = new List<UserDetails>();
                if (_userDetails != null)
                {
                    userDetails = (from ud in _userDetails where ud.active_yn select ud).ToList();
                }
                return userDetails;
            }
             set { _userDetails = value; }
        }

    }
}

用户详细信息类

namespace myclass.Core.Domain.Customers
{
    public partial class UserDetails : BaseEntity
    {
        private User _updatedByUser;

        public virtual long user_id { get; set; }
        public virtual string primary_specialty { get; set; }
        public virtual string secondary_specialty { get; set; }
        public virtual string npi { get; set; }
        public virtual string state_licence_number { get; set; }
        public virtual string issuing_state { get; set; }
        public virtual string dea_number { get; set; }
        public virtual string dea_schedule1 { get; set; }
        public virtual string dea_schedule2 { get; set; }
        public virtual string dea_schedule3 { get; set; }
        public virtual string dea_schedule4 { get; set; }
        public virtual string dea_schedule5 { get; set; }
        public virtual string dea_expire_date { get; set; }
        public virtual string state_licence_expire_date { get; set; }
        public virtual string provider_rights { get; set; }
        public virtual long updated_by_user_id { get; set; }
        public virtual User updatedByUser
        {
            get { return _updatedByUser; }
            protected set
            {
                _updatedByUser = value;
                updated_by_user_id = _updatedByUser.Id;
            }
        }
    }
}

对于我的映射,我对用户和用户详细信息都有以下结构 用户地图

namespace myclass.Data.Mappings.Domains.Customers
{
    public partial class UserMap : EntityTypeConfiguration<User>
    {
        public UserMap()
        {
            this.ToTable("users");
            this.HasKey(u => u.Id);
            this.Property(u => u.Id).HasColumnName("user_id");
            this.Property(u => u.userguid).IsRequired();
            this.Property(u => u.first_name).HasMaxLength(50).IsRequired();
            this.Property(u => u.last_name).HasMaxLength(50).IsRequired();
            this.Property(u => u.pwrd).HasMaxLength(100).IsRequired();
            this.Property(u => u.email_address).HasMaxLength(100).IsRequired();
            this.Property(u => u.loginname).HasMaxLength(50).IsRequired();
            this.Property(u => u.activated_date).IsOptional();
            this.Property(u => u.create_date).IsRequired();
            this.Property(u => u.active_yn).IsRequired();
            this.Property(u => u.title).IsOptional();
            this.Property(u => u.suffix).IsOptional();
            this.Property(u => u.last_four_ssn).IsOptional();
            this.Property(u => u.secretquestion).IsOptional();
            this.Property(u => u.secretanswer).IsOptional();
            this.Property(u => u.birthyear).IsOptional();
            this.Property(u => u.account_status).IsOptional();
            this.Property(u => u.suspended_yn).IsOptional();

            this.HasMany(u => u.userDetails).WithRequired().HasForeignKey(ud => ud.user_id);
            this.HasMany(u => u.usersSitesAcls).WithRequired().HasForeignKey(usa => usa.user_id);
            this.HasMany(u => u.companiesAcls).WithRequired().HasForeignKey(ca => ca.user_id);
        }
    }
}

用户详情地图

enter code here
namespace myclass.Data.Mappings.Domains.Customers
{
    public partial class UserDetailsMap:EntityTypeConfiguration<UserDetails>
    {
        public UserDetailsMap()
        {
            this.ToTable("user_details");
            this.HasKey(ud => ud.Id);
            this.Property(ud => ud.Id).HasColumnName("user_detail_id");
            this.Property(ud => ud.user_id).IsRequired();
            this.Property(ud => ud.primary_specialty).HasColumnName("primary_speciality").IsOptional();
            this.Property(ud => ud.secondary_specialty).IsOptional();
            this.Property(ud => ud.npi).IsOptional();
            this.Property(ud => ud.state_licence_number).HasColumnName("StateLicenseNumber").IsOptional();
            this.Property(ud => ud.issuing_state).HasColumnName("IssuingState").IsOptional();
            this.Property(ud => ud.dea_number).HasColumnName("DEANumber").IsOptional();
            this.Property(ud => ud.dea_schedule1).HasColumnName("DEASchedule1").IsOptional();
            this.Property(ud => ud.dea_schedule2).HasColumnName("DEASchedule2").IsOptional();
            this.Property(ud => ud.dea_schedule3).HasColumnName("DEASchedule3").IsOptional();
            this.Property(ud => ud.dea_schedule4).HasColumnName("DEASchedule4").IsOptional();
            this.Property(ud => ud.dea_schedule5).HasColumnName("DEASchedule5").IsOptional();
            this.Property(ud => ud.dea_expire_date).HasColumnName("DeaExpireDate").IsOptional();
            this.Property(ud => ud.state_licence_expire_date).HasColumnName("StateLicenseExpireDate").IsOptional();
            this.Property(ud => ud.provider_rights).HasColumnName("ProviderRights").IsOptional();
            this.Property(ud => ud.active_yn).IsRequired();
            this.Property(ud => ud.create_date).IsRequired();
            this.Property(ud => ud.updated_by_user_id).IsRequired();

            this.HasRequired(ud => ud.updatedByUser).WithMany().HasForeignKey(ud => ud.updated_by_user_id);
        //
}
    }
}

首先我要添加一条新记录,然后设置 User 类的内容(禁止 User_details 和 user_acls,然后它会为用户创建记录而没有任何问题。

但是,当我尝试对 user_details 和 user_acls 执行相同操作时,我没有任何成功,并尝试将 user_details 作为项目添加到用户表上的属性中,但没有任何成功。

甚至尝试将其保存为单独的记录,我在其中存储用户记录,检索添加的新记录的 user_id。然后为 user_details 和 user_acls 创建一个新对象,并尝试保存它,我最终得到以下消息:

我需要做些什么来完成这项工作,我已经尝试了我所知道的一切,但没有成功。因此,您可以提供的任何帮助将不胜感激。谢谢。

块引用 操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

【问题讨论】:

    标签: c# entity-framework-5 poco


    【解决方案1】:

    我发现了这一点,这与我使用 autofac 访问用户对象的方式有关,最后它是我的结果。

    【讨论】:

      【解决方案2】:

      您显示了很多代码,但我怀疑没有显示有问题的代码。即您如何创建用户并附加用户详细信息以及如何保存这些对象。

      一个简单的测试可以使用

      this.Ignore(ud=>ud.User) 
      

      作为用户详细信息映射的一部分。

      如果这可行,您可以相当确定问题是与 UserDetail 关联的用户的状态不是未更改。应该发生的是,应该首先保存用户,然后将其状态设置为未更改,然后应该保存用户详细信息。

      因为您没有显示您的附加和保存代码,我只能推测,但我敢打赌,如果您使用断开连接的实体,用户的状态不是未更改,可能是已添加或某些自定义状态,例如 Inactive。

      因此,EF 尝试重新创建用户对象(如果状态 == 已添加),然后将其重新分配给 UserDetails,这会通过使先前的用户对象关联为空然后附加新的关联来以某种方式孤立用户详细信息。

      我仍在研究文档以确切了解这是如何发生的,但我自己在过去半小时内的经验是,父/外键对象的状态不是未更改。因此,EF 将用户详细信息对象中的用户引用与其 DBSet 中的引用区分开来。因此是空引用。

      我了解您正在同时保存新用户及其详细信息,但请仔细查看您的代码以了解您是如何执行此操作的。很可能发生了某种“用户交换”,您首先保存的用户实际上并不是在尝试保存它们时附加到 UserDetails 的用户。你是否在做任何 Linq ToList() 类型的“东西”并无意中切换到非 Unchanged User 对象的引用。

      在我的情况下,这是因为我在数据库中的 FK 对象的代码中创建了一个“存根”对象,并且在将其与我的详细信息对象关联之前,我忽略了它的状态设置为未更改。

      很抱歉,我的回答有点胡扯,但我现在只是在处理它。当我更清楚地理解它时,我会更新这个答案。

      【讨论】:

        【解决方案3】:

        要阅读的代码很多,但我认为问题在于您正在修改实体状态,而实体框架并未对其进行跟踪。

        试试类似的东西

             db.Entry(currentyUser).State = EntityState.Modified;
        

        在保存更改之前。

        【讨论】:

        • 我应该在这里添加,这是使用存储库模式来写出记录,所以在我设置对象后,我将它传递给存储库插入方法。其中有以下代码。
        • if(entity == null) throw new ArgumentNullException("entity"); this.Entities.Add(实体); this._context.SaveChanges(); _inserted_record_id = entity.Id;
        • 我应该在这里注意的另一件事是,这仅在我存储新用户时发生。我添加了用户,然后我添加了 user_details,它不存在并且没有与该用户关联的记录被添加到数据库中。它创建用户记录,只是没有子记录。
        猜你喜欢
        • 2015-12-16
        • 2013-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多