首页 > 解决方案 > 为什么 EF Seed 方法在 DateTime 上插入 Null?

问题描述

我正在尝试在我的 Code-First EF 6 项目中实现 AddOrUpdate 方法。我收到一条错误消息,指出属性 AdmCreatedDate 中不允许使用空值。错误下方:

运行种子方法。System.Data.Entity.Infrastructure.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> System.Data.Entity.Core.UpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> System.Data.SqlClient.SqlException:无法将值 NULL 插入到列“AdmCreatedDate”、表“TPPX.dbo.ExemptionCalculationConfig”中;列不允许空值。插入失败。该语句已终止。

这是我的代码...我有一个名为 ExemptionCalculationConfig 的模型:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TPPX.Domain.ExemptionModels.Entities.Lookups;

namespace TPPX.Domain.ExemptionModels
{
    [Table("ExemptionCalculationConfig")]
    public class ExemptionCalculationConfig : TPPXBaseEntity
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Priority { get; set; }

        [ForeignKey("ExemptionApplyLevel")]
        public string ApplyAtLevelCode { get; set; }

        public virtual ExemptionApplyLevel ExemptionApplyLevel { get; set; }

        [ForeignKey("ExemptionApplyType")]
        public string ApplyByValueOrPercentageCode { get; set; }

        public virtual ExemptionApplyType ExemptionApplyType { get; set; }
        public bool IsProratable { get; set; }
    }
}

如你所见,这个类继承了 TPPXBaseEntity:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;

namespace TPPX.Domain
{
    public class TPPXBaseEntity
    {
        [DefaultValue(true)]
        public bool IsActive { get; set; }

        public DateTime  AdmCreatedDate { get; set; }

        [StringLength(50)]
        public string AdmCreatedUser { get; set; }

        [StringLength(255)]
        public string AdmCreatedUserFullName { get; set; }
        public DateTime? AdmModifiedDate { get; set; }

        [StringLength(50)]
        public string AdmModifiedUser { get; set; }

        [StringLength(255)]
        public string AdmModifiedUserFullName { get; set; }

    }
}

然后我的 Migrations 文件夹中有我的 Configuration.cs 文件:我尝试添加要保存在数据库中的对象列表以及单个实例。此外,我明确尝试创建一个名为 seedCreatedDate 的 DateTime 对象,使用 DateTime.Today 甚至 DateTime.ParseExact() 作为 AdmCreatedDate 的值,但没有运气:(

using System.Collections.Generic;
using System.Web;
using PA.Web.Configuration.WebConfigurationManager;
using TPPX.Domain.ExemptionModels;
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;

namespace TPPX.DAL.Migrations.TPPXDBContext
{


    internal sealed class Configuration : DbMigrationsConfiguration<TPPX.DAL.DBContexts.TPPXDBContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            MigrationsDirectory = @"Migrations\TPPXDBContext";
        }

        protected override void Seed(TPPX.DAL.DBContexts.TPPXDBContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data.
            //var seedCreatedDate = new DateTime(2018, 07, 26);

            //var exemptionCalculationConfigs = new List<ExemptionCalculationConfig>
            //{
            //    new ExemptionCalculationConfig
            //    {
            //        AdmCreatedDate = DateTime.Today,
            //        AdmCreatedUser = "carcruz",
            //        AdmCreatedUserFullName = "Cruz, Carlos (PA)",
            //        Priority = 1,
            //        IsProratable = false,
            //        ApplyAtLevelCode = "A",
            //        ApplyByValueOrPercentageCode = "P",
            //        IsActive = true
            //    },
            //    new ExemptionCalculationConfig
            //    {
            //        AdmCreatedDate = DateTime.Today,
            //        AdmCreatedUser = "carcruz",
            //        AdmCreatedUserFullName = "Cruz, Carlos (PA)",
            //        Priority = 2,
            //        IsProratable = false,
            //        ApplyAtLevelCode = "V",
            //        ApplyByValueOrPercentageCode = "V",
            //        IsActive = true
            //    }
            //};

            //exemptionCalculationConfigs.ForEach(
            //    x => context.ExemptionCalculationConfigs.AddOrUpdate(e => e.Priority, x));

            context.ExemptionCalculationConfigs.AddOrUpdate(
                e => e.Priority,
                new ExemptionCalculationConfig
                {
                    AdmCreatedDate = DateTime.Now,
                    AdmCreatedUser = "carcruz",
                    AdmCreatedUserFullName = "Cruz, Carlos (PA)",
                    Priority = 1,
                    IsProratable = false,
                    ApplyAtLevelCode = "A",
                    ApplyByValueOrPercentageCode = "P",
                    IsActive = true,
                    AdmModifiedDate = null,
                    AdmModifiedUser = null,
                    AdmModifiedUserFullName = null
                });
            context.SaveChanges();
        }
    }
}

当其他人没有明确说他们的主键不应该是标识列时,我已经看到其他人也有同样的错误,但这不是我的情况。我错过了什么?

标签: c#entity-frameworkentity-framework-6

解决方案


好吧,伙计们。

我想通了(有点)。

感谢 IvanStoev 指出计算和身份属性。

我的 DbContext 中确实有以下行:

modelBuilder.Properties<DateTime>().Where(x => x.Name == "AdmCreatedDate")
.Configure(c => c.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed));

由于某种原因,当 Seed 方法尝试运行并且对象具有计算属性时,EF 不喜欢它。我与项目负责人交谈并说服她从 EF 中计算出来(因为它甚至不会影响数据库。EF 仅在代码上处理它。在 SQL Server 中检查数据库后,我注意到该列实际上并未设置为计算)老实说,我不喜欢这样,因为如果将来我们决定不使用 EF,计算的属性将会丢失。

因此,总而言之,您不能在 Seed() 方法中拥有具有计算属性的模型

现在,我们处理实际数据库中的计算列。

很高兴知道,我无法在网上找到这就是为什么 EF 会以这种方式运行。如果有人知道,请告诉我。

希望这可以帮助 :)


推荐阅读