2016-11-30 86 views
0

我有表:供应商和品牌和基地抽象类净EF记录没有保存在数据库中(InvalidOperationException异常)

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)的代码示例

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(); 
     } 
    } 
} 

上保存我得到一个错误:

Exception thrown: 'System.InvalidOperationException' in EntityFramework.dll

Additional information: The operation failed: The relationship could not be > changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

保存前我保留3210

我选中了品牌。大部分供应商都是空的,但VendorID已填满。 我试图在方法添加此在服务创建

Vendor = _vendorRepository.GetById(entityModel.VendorID) 

但之后,从供应商字段的AddRange数据消失%)

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

+0

'SubBrand'代码在哪里? – grek40

+0

@ grek40我觉得没关系。代码与品牌类似,没有什么新意。你认为这很重要吗? –

回答

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); 
     } 
    } 
+0

对于'Vendor',我们在问题中看到'VendorID'。比'ID'更适合作为外键。除了这个细节外,看起来像是一个很好的捕获,我忽略了缺少的外键规范。 – grek40

+0

我向供应商和接收者添加了'HasForeignKey(e => e.ID)'错误: _Exception在EntityFramework中抛出了'System.Data.Entity.ModelConfiguration.ModelValidationException'。在关系多重不作用有效的“Vendor_Brand_Target”“Vendor_Brand”:dll的 其他信息:模型生成期间检测到一个或多个验证错误: Vendor_Brand_Target:因为依赖角色是指关键属性,所以从属角色的多重性的上界必须是'1'._ –

+0

@ evg.vis这就是为什么你应该说'HasForeignKey(e => e.VendorID)'。 – grek40

0

我需要说抱歉浪费你的时间。我没有复制我的抽象类实体的所有代码,这就是为什么你不能帮助我。在抽象类实体中,我已经实现了比较的基本方法。

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

我已评论比较的基本方法,一切正在工作:)

ps。脾脏感谢@ grek40;)

+0

我有时会重新访问我最近的问题评论,我总是很高兴看到它的解决方案;)顺便说一句,你是不是这个问题的第一个。尚未初始化的实体ID被视为独特的问题每隔一段时间就会突然出现,绝对是棘手的问题之一。尽管如此,如果你不写更多的道歉和感谢故事,而更多的是有条理的解释答案,帮助其他人也可以通过ID比较实体而无需再次思考的话,我仍然会更喜欢它。 – grek40