.Net EF记录未保存在数据库中(InvalidOperationException)

时间:2016-11-30 07:44:51

标签: c# .net entity-framework

我有表:供应商和品牌以及基本抽象类

public abstract class Entity<TEntity, TKeyType> : IEntity<TEntity, TKeyType>
    where TEntity : class
{
    [Key]
    public virtual TKeyType ID { get; set; }

    public virtual bool IsDeleted { get; set; }

    #region Equals
    public virtual bool Equals(Entity<TEntity, TKeyType> other)
    {
        if (ReferenceEquals(this, other))
            return true;
        if (other == null || !(other is TEntity))
            return false;
        return ID.Equals(other.ID);
    }

    public override bool Equals(object obj)
    {
        var compareTo = obj as Entity<TEntity, TKeyType>;
        return Equals(compareTo);
    }

    public override int GetHashCode()
    {
        return ID.GetHashCode();
    }
    #endregion
}

实体:

public partial class Vendor : Entity<Vendor, long>
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Vendor()
    {
        Brand = new HashSet<Brand>();
    }

    [Required]
    [StringLength(32)]
    public string Name { get; set; }

    public Guid Guid { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Brand> Brand { get; set; }
}

public partial class Brand : Entity<Brand, long>
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Brand()
    {
        SubBrand = new HashSet<SubBrand>();
    }

    [Required]
    [StringLength(64)]
    public string Name { get; set; }

    public Guid Guid { get; set; }

    public long VendorID { get; set; }

    public virtual Vendor Vendor { get; set; }
}

ODMSDBContext:

public partial class ODMSDBContext : DbContext
{
    public ODMSDBContext() : base("name=ODMSConnection") { }

    public virtual DbSet<Vendor> Vendor { get; set; }
    public virtual DbSet<Brand> Brand { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Brand>()
            .Property(e => e.ExtraCode)
            .IsUnicode(false);

        modelBuilder.Entity<Brand>()
            .Property(e => e.Name)
            .IsUnicode(false);

        modelBuilder.Entity<Brand>()
            .HasMany(e => e.SubBrand)
            .WithRequired(e => e.Brand)
            .HasForeignKey(e => e.BrandID)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Vendor>()
            .Property(e => e.Name)
            .IsUnicode(false);

        modelBuilder.Entity<Vendor>()
            .HasMany(e => e.Brand)
            .WithRequired(e => e.Vendor)
            .HasForeignKey(e => e.VendorID)
            .WillCascadeOnDelete(false);
    }
}
服务中的

存在方法 - 创建

    public override void Create(IEnumerable<EntityModel> models)
    {
        var entities = new List<Brand>();

        foreach (var model in models)
        {
            var entityModel = model as BrandModel;
            var entity = new Brand
            {
                Guid = entityModel.Guid,
                VendorID = entityModel.VendorID,
                Name = entityModel.Name,
                SortOrder = entityModel.SortOrder,
                ExtraCode = entityModel.ExtraCode
            };

            entities.Add(entity);
        }
        _repository.Create(entities);

        _repository.Save();
    }

来自Repository(_repository)

的代码示例
public class EntityRepository<TEntity, TKeyType> : IEntityRepository<ODMSDBContext, TEntity, TKeyType>
where TEntity : class, IEntity<TEntity, TKeyType>
{
    private readonly ODMSDBContext _context;
    private DbSet<TEntity> DbSet => _context.Set<TEntity>();

    public EntityRepository(ODMSDBContext context)
    {
        _context = context;
    }

    ...

    public void Create(IEnumerable<TEntity> entities)
    {
        DbSet.AddRange(entities);
    }

    public void Save()
    {
        _context.SaveChanges();

        transaction.Commit();
        }
    }
}

关于保存我收到错误:

  

抛出异常:&#39; System.InvalidOperationException&#39;在EntityFramework.dll

中      

附加信息:操作失败:关系不能是&gt;因为一个或多个外键属性不可为空而更改。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

保存前我检查了品牌。最重要的供应商是null,但VendorID已填满。 我尝试在方法Create

中的Service中添加它
Vendor = _vendorRepository.GetById(entityModel.VendorID)

但在供应商字段的AddRange数据消失后%)

UPD。我创建了一个描述奇怪行为的小视频 - http://screencast.com/t/RI32v4gu

2 个答案:

答案 0 :(得分:0)

我没有看到Key数据注释,或者您在Fluent API中设置了实际的键。

尝试更改modelBuilder覆盖以在每个实体上显式设置外键。

    public partial class ODMSDBContext : DbContext
    {
        public ODMSDBContext() : base("name=ODMSConnection") { }

        public virtual DbSet<Vendor> Vendor { get; set; }
        public virtual DbSet<Brand> Brand { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Brand>()
                .Property(e => e.ExtraCode)
                .IsUnicode(false);

            modelBuilder.Entity<Brand>()
                .Property(e => e.Name)
                .IsUnicode(false);

            modelBuilder.Entity<Brand>()
                .HasMany(e => e.SubBrand)
                .WithRequired(e => e.Brand)
                .HasForeignKey(e=>e.ID)
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<Vendor>()
                .Property(e => e.Name)
                .IsUnicode(false);

            modelBuilder.Entity<Vendor>()
                .HasMany(e => e.Brand)
                .WithRequired(e => e.Vendor)
                .HasForeignKey(e=>e.ID)
                .WillCascadeOnDelete(false);
        }
    }

答案 1 :(得分:0)

我需要为浪费你的时间而感到抱歉。我没有复制我的抽象类实体的所有代码,这就是你无法帮助我的原因。在抽象类Entity中,我实现了用于比较的基本方法。

当我尝试向供应商添加新品牌时,所有品牌中的字段ID等于0.此值与HashSet中存在的比较,借助我的比较基本方法,并且未添加新记录,因为Brand此列表中确实存在ID = 0。

我评论了比较的基本方法,一切正常:)

PS。请感谢@ grek40;)