2016-04-14 8 views
1

ich GraphDiff nicht zum Nullwerten verwenden können, um detached Objektdiagramme zu aktualisieren, und ich bekomme die obige Ausnahme beim Speichern eines übergeordneten Objekts und seiner untergeordneten Elemente.Die Beziehung konnte nicht geändert werden, weil eine oder mehrere Eigenschaften des Fremdschlüssels beim Speichern

Die Modelle und Mapping sind:

public class Group 
{ 
    public int Id { get; set; } 
    public virtual ICollection<GroupUser> Users{ get; set; } 
} 

public class GroupUser 
{ 
    public int Id { get; set; } 
    public int GroupId { get; set; } 
    public int UserId { get; set; } 
    public virtual User User { get; set; } 
} 

public class GroupMap : EntityTypeConfiguration<Group> 
{ 
    public GroupMap() 
    { 
     this.ToTable("groups"); 
     this.HasKey(t => t.Id).Property(t => t.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

     this.HasMany(t => t.Users) 
      .WithOptional() 
      .HasForeignKey(d => d.GroupId) 
      .WillCascadeOnDelete(); 
    } 
} 

public class GroupUserMap : EntityTypeConfiguration<GroupUser> 
{ 
    public GroupUserMap() 
    { 
     this.ToTable("groups_users"); 
     this.HasKey(t => t.Id).Property(t => t.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     this.Property(t => t.GroupId).HasColumnName("group_id").IsRequired(); 
     this.Property(t => t.UserId).HasColumnName("user_id").IsRequired(); 

     this.HasRequired(t => t.User) 
      .WithMany() 
      .HasForeignKey(d => d.UserId) 
      .WillCascadeOnDelete(false); 
    } 
} 

Für Einsätze und Updates ich das folgende Verfahren in meinem Repository:

public override Group Update(Group entity) 
{ 
    if (entity.Users != null) 
    { 
     entity.Users.ToList() 
        .ForEach(x => 
        { 
         x.GroupId = x.Id == 0 ? 0 : entity.Id; 
         x.UserId = x.User.Id; 
        }); 
    } 

    return dbContext.UpdateGraph<Group> 
     (entity, 
      map => map.OwnedCollection(x => x.Users, with => with.AssociatedEntity(c => c.Users)) 
     ); 
} 

ich folgendes:

  1. ein In neue Gruppe, speichern und neu laden
  2. Hinzufügen eines Benutzers zu der Gruppe, speichern und erneut Last
  3. einen zweiten Benutzer hinzufügen, speichern und
  4. hinzufügen dritten Benutzer neu zu laden, versuchen zu retten -> Ausnahme
  5. Während das Debuggen

geworfen wird, der Zustand der Benutzerentitäten immer gelöst wird hinzugefügt, und Sowohl GroupId als auch Id werden für neue Entitäten auf 0 gesetzt. Die ersten 2 hinzugefügten Benutzer werden erfolgreich gespeichert. Bei der dritten wird jedoch die Ausnahme ausgelöst.

Wenn ich immer die gleiche Methode zum Speichern verwende, warum funktioniert es nicht immer? Ist es ein EF oder GraphDiff Problem und gibt es eine Möglichkeit, dieses Problem zu lösen?

Die meisten Fragen und zugehörigen Antworten hier auf SO und anderswo befassen sich alle mit der Situation, in der eine untergeordnete Entität gelöscht wird. Dies ist in meinem speziellen Szenario nicht der Fall.

Antwort

0

Wahrscheinlich nicht nullable auf Benutzer-ID verknüpft ist. Wie Sie wissen, wird UserId von EF verwendet, um Benutzer zu schreiben. Wenn Benutzer null ist (kann es), kann EF die Entität nicht schreiben. Es könnte auch mit User.GroupId verwandt werden, das von EF verwandt wird, um die Group.Users-Auflistung zuzuordnen.

Auch ich kann Ihr Modell nicht verstehen. Ein Benutzer hat eine und nur eine Gruppe. Eine Gruppe kann mehr als einen Benutzer haben.

Wenn dies zutrifft, warum vereinfachen Sie nicht einfach Ihr Modell, indem Sie die Assoziationseinheit entfernen? EF braucht es nicht ...

public class Group 
{ 
    public int Id { get; set; } 
    public virtual ICollection<User> Users{ get; set; } 
} 

public class User 
{ 
    public int Id { get; set; } 
    public virtual Group Group { get; set; } 
} 

In diesem Fall brauchen Sie nur UserMap.

public class UserMap : EntityTypeConfiguration<User> 
{ 
    public UserMap() 
    { 
     // You don't need to set primary key. EF take Id and create an identity column 
     //HasKey(t => t.Id); 

     // Table & Column Mappings 
     ToTable("users"); 
     // No column mappings in this case. 

     // Relationships 
     HasRequired(t => t.Group) 
      .WithMany(t => t.Users) 
      .Map(d => d.MapKey("user_group")); 

    } 
} 

Wenn ein Benutzer mehr als eine Gruppe haben, können Sie können einfach Ihren Benutzermodell auf diese Weise modifizieren

public class User 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Group> Groups { get; set; } 
} 

EF versteht, dass ein viele zu viele Beziehung ist, wird die Zuordnungstabelle (UsersGroups erstellen), aber Sie brauchen die Assoziationseinheit nicht.

EDIT

Selten müssen Sie db.Entry(myEntity).State = EntityState.Modified; mit EF6 einzustellen. Proxies funktioniert ganz gut.

1

Haben Sie versucht zu sehen, ob der Entitätsstatus geändert wird, wenn er nicht von EF verfolgt wird?

Versuchen

db.Entry(currentUser).State = EntityState.Modified; 

Die ToList() Funktion auch versehentlich den Benutzerstatus zu modifizieren Sie verursachen könnte zu.

+0

Das Ändern von 'ToList()' zu einer normalen 'foreach' machte keinen Unterschied. –

+0

'State' ist hinzugefügt was korrekt ist. –

+0

Wenn der 'Status' hinzugefügt und nicht unverändert ist, klingt es wie ein Problem mit einer Trennung von Entitäten. Meine Vermutung ist, dass EF den 'GroupUser' neu erstellt und dann den vorherigen 'GroupUser' beim Speichern löscht. Haben Sie versucht, die Werte der zuvor hinzugefügten Benutzer zu drucken? – kermitvomit

0

bitte versuchen Sie es this.it ungetestet ist aber

public override Group Update(Group entity) 
{ 
    if (entity.Users != null) 
    { 
     foreach(var user in entity.Users){ 
      user.GroupId = x.Id == 0 ? 0 : entity.Id; 
      user.UserId = x.User.Id; 
     dbContext.Entry(child).State = EntityState.Modified; 
     } 

    } 

    return dbContext.UpdateGraph<Group> 
     (entity, 
      map => map.OwnedCollection(x => x.Users, with => with.AssociatedEntity(c => c.Users)) 
     ); 
} 
Verwandte Themen