2016-11-30 3 views
0

データベース(InvalidOperationExceptionが)に保存されていない:ベンダーおよびブランドとベース抽象クラスネットEFレコードが、私はテーブルを持っている

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

を(_repository)を

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

とコードのサンプルを作成します。

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

私はブランドをチェックしました。ほとんどのベンダーはnullですが、VendorIDは満たされています。 は私が)

UPDを

Vendor = _vendorRepository.GetById(entityModel.VendorID) 

を作成しますが、ベンダーフィールドからAddRangeデータが消滅した後に%方法でサービスでこれを追加しようとしました。私は奇妙な動作を記述する小さなビデオを作成しました。 - http://screencast.com/t/RI32v4gu

+0

「SubBrand」コードはどこですか? – grek40

+0

@ grek40問題ではないと思います。コードはBrandと同じですが、新しいものはありません。それは重要だと思いますか? –

答えて

0

私はキーのデータ注釈が表示されないか、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'。dll 追加情報:モデル生成中に1つ以上の検証エラーが検出されました。 Vendor_Brand_Target :: Multiplicityは、関係 'Vendor_Brand'のロール 'Vendor_Brand_Target'では無効です。 Dependent Roleはキープロパティを参照するため、Dependent Roleの多重度の上限は '1'でなければなりません。._ –

+0

@ evg.visなぜ、あなたは 'HasForeignKey(e => e.VendorID)'と言うべきですか? – grek40

0

私はあなたの時間を無駄にして申し訳ありません。抽象クラスEntityのすべてのコードをコピーしていないので、あなたが私を助けなかったのです。抽象クラスEntityでは、私は比較のための基本メソッドを実現しました。

ベンダーに新しいブランドを追加しようとしたとき、すべてのブランドのフィールドIDは0でした。この値は、比較のためのベースメソッドの助けを借りてHashSetに存在するものと比較され、このリストには、ID = 0のブランドは存在しません。

私は比較して、すべてが:)

PSを働いているため基本メソッドをコメントしています。 @ grek40への特別な感謝;)

+0

私は時々、私の最近の質問のコメントを再訪しています。いつ解決されるかはいつもうれしいよ;)ところで、あなたはこの問題の最初のものではありません。まだ初期化されていないエンティティIDの問題は、毎回ユニークなポップアップとして扱われ、トリッキーな獣の間では間違いありません。それでも、謝罪と感謝のストーリーを少なく書くと、もう少し考えずにIDでエンティティを比較するかもしれない他の人を助ける、構造化されたよく説明された回答のほうが好きです。 – grek40

関連する問題