2016-11-30 3 views
0

Ich habe Tabellen: Hersteller und Marke und Basis abstrakte Klasse.Net EF Datensätze in der Datenbank (InvalidOperationException) nicht gespeichert

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 
} 

Entity:

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

und

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:


in Service existieren Verfahren - Erstellen

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

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

auf Speichern Ich erhalte eine Fehlermeldung:

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.

vor dem Speichern habe ich Marke überprüft. Anbieter ist in den meisten Fällen Null, aber VendorID ist gefüllt. Ich habe versucht, dies in Verfahren

Vendor = _vendorRepository.GetById(entityModel.VendorID) 

erstellen in Service hinzuzufügen, aber nach AddRange Daten aus Lieferantenfeld sind verschwunden%)

upd. Ich habe ein kleines Video erstellt, das seltsames Verhalten beschreibt - http://screencast.com/t/RI32v4gu

+0

Wo ist 'SubBrand' Code? – grek40

+0

@ grek40 Ich denke es ist egal. Code ist ähnlich wie in Brand, nichts Neues. denkst du ist es wichtig? –

Antwort

0

Ich sehe keine Key Data Annotation oder Sie setzen die tatsächlichen Schlüssel in Fluent API.

Versuchen Sie, Ihre modelBuilder-Überschreibungen zu ändern, um die Fremdschlüssel für jede Entität explizit festzulegen.

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

Für 'Vendor' sehen wir' VendorID' in der Frage. Wäre besser geeignet als ID als Fremdschlüssel. Abgesehen von diesem Detail, das wie ein guter Fang aussieht, habe ich die fehlende Fremdschlüssel-Spezifikation übersehen. – grek40

+0

Ich habe 'HasForeignKey (e => e.ID) 'zu Hersteller und Empfänger einen Fehler hinzugefügt: _Exception geworfen:' System.Data.Entity.ModelConfiguration.ModelValidationException 'in EntityFramework.dll Weitere Informationen: Bei der Modellerstellung wurden ein oder mehrere Validierungsfehler festgestellt: Vendor_Brand_Target:: Die Multiplizität ist in der Rolle 'Vendor_Brand_Target' in der Beziehung 'Vendor_Brand' nicht gültig. Da sich die abhängige Rolle auf die Schlüsseleigenschaften bezieht, muss die Obergrenze der Multiplizität der abhängigen Rolle '1' sein ._ –

+0

@ evg.vis Deshalb sollten Sie stattdessen 'HasForeignKey (e => e.VendorID)' sagen. – grek40

0

Ich muss mich entschuldigen, dass Sie Ihre Zeit verschwenden. Ich habe nicht meinen gesamten Code für abstrakte Klassen-Entitäten kopiert und deshalb konnten Sie mir nicht helfen. In der abstrakten Klasse Entity habe ich Basismethoden zum Vergleichen realisiert.

Als ich dem Hersteller neue Marken hinzufügen wollte, war Feld-ID in allen Marken gleich 0. Dieser Wert wurde in HashSet mit Hilfe meiner Basismethoden zum Vergleichen verglichen, und neue Datensätze wurden nicht hinzugefügt, weil Marke mit ID = 0 existiert in dieser Liste.

Ich habe Basismethoden kommentiert zum Vergleichen und alles :)

ps arbeitet. Danke an @ grek40;)

+0

Ich besuche manchmal meine letzten Fragekommentare und bin immer froh zu sehen, wann es gelöst wurde;) Übrigens bist du es auch nicht der erste mit diesem Problem. Probleme mit noch nicht initialisierten Entity-IDs werden immer wieder als eindeutige Popups behandelt und zählen definitiv zu den kniffligen Biestern. Trotzdem würde ich es bevorzugen, wenn Sie weniger von einer Entschuldigung & Dankgeschichte schreiben und mehr von einer strukturierten gut erklärten Antwort, die anderen hilft, die auch Entitäten nach ID ohne einen zweiten Gedanken vergleichen könnten. – grek40

Verwandte Themen