1

importieren will ich mit dem Code beginnen, die Probleme verursacht nur für den Fall gibt es etwas super offensichtlich ist, dass ich fehle:EF Kern: Ich beende mit Dubletten in der Datenbank, wenn Datensätze mit json.net

foreach(JToken OrgToken in json["Orgs"]) { 
    Debug.WriteLine("Org " + OrgToken["Name"]); 
    Org o = OrgToken.ToObject <Org>(); 
    _cont.Orgs.Add(o); 
    _influxClient.CreateDatabaseAsync(o.MetricDatabaseName); 

    foreach(JToken PortfolioToken in OrgToken["Portfolios"]) { 
     Debug.WriteLine("Portfolio " + PortfolioToken["Name"]); 
     Portfolio p = PortfolioToken.ToObject <Portfolio>(); 
     p.OrganizationId = o.Id; 
     _cont.Portfolios.Add(p); 

     foreach(JObject ProjectToken in PortfolioToken["Projects"]) { 
      Debug.WriteLine("Project " + ProjectToken["Name"]); 
      Project prj = ProjectToken.ToObject <Project>(); 
      prj.PortfolioId = p.Id; 
      _cont.Projects.Add(prj); 
      _cont.SaveChanges(); 
     } 
    } 
} 
_cont.SaveChanges(); 

Diese Code wird eine Hierarchie verwandter Objekte (Org-> Portfolio-> Project) aus einer JSON-Datei laden:

{ 
    "Orgs": [ 
    { 
     "Name": "StrongSoft", 
     "Users": [ 
     { 
      "email": "[email protected]", 
      "password": "password", 
      "IsOrgAdmin": true 
     }, 
     { 
      "email": "[email protected]", 
      "password": "password", 
      "IsOrgAdmin": false 
     } 
     ], 
     "Portfolios": [ 
     { 
      "Name": "Financial", 
      "Projects": [ 
      { "Name": "Derivatives Trading" }, 
      { "Name": "Fixed Income" }, 
      { "Name": "Fix Market Connector" } 
      ] 
     }, 
     { 
      "Name": "Machinery", 
      "Projects": [ 
      { "Name": "Hard Metal Stuff" }, 
      { "Name": "Health Management Framework" }, 
      { "Name": "Look and Poock" } 
      ] 
     }, 
     { 
      "Name": "Lab", 
      "Projects": [ 
      { "Name": "[email protected]#$%^&*()_+++++++++w+" }, 
      { "Name": "Какое-то странное имя, это капец" }, 
      { "Name": "" } 
      ] 
     } 
     ] 
    }, 
    { 
     "Name": "Clevereer", 
     "Users": [ 
     { 
      "email": "[email protected]", 
      "password": "password", 
      "IsOrgAdmin": true 
     }, 
     { 
      "email": "[email protected]", 
      "password": "password", 
      "IsOrgAdmin": false 
     } 
     ], 
     "Portfolios": [ 
     { 
      "Name": "Prospects", 
      "Projects": [ 
      { "Name": "AI Assisted Surveillance" }, 
      { "Name": "Metrics Keeper" } 
      ] 
     } 
     ] 
    } 
    ] 
} 

Das Problem, das ist, wenn diese läuft, I 2 Duplikate am Ende mit für jeden der Portfolio Objekte und 3 Duplikate für jeden der Project. Org kommt ohne Duplikate.

Ich habe dafür gesorgt, dass die Schleifen richtige Anzahl von „Haltestellen“ machen und die Objekte werden versucht nur einmal erstellt werden (daher der Debug.WriteLine()):

Org StrongSoft 
Portfolio Financial 
Project Derivatives Trading 
Project Fixed Income 
Project Fix Market Connector 
Portfolio Machinery 
Project Hard Metal Stuff 
Project Health Management Framework 
Project Look and Poock 
Portfolio Lab 
Project [email protected]#$%^&*()_+++++++++w+ 
Project Какое-то странное имя, это капец 
Project 
Org Clevereer 
Portfolio Prospects 
Project AI Assisted Surveillance 
Project Metrics Keeper 

Ich versuchte SaveChanges() und Attach() Routinen

Ich habe versucht, EntityState der hinzugefügten Objekte zu ändern, so dass EF nicht davon ausgeht, dass sie geändert werden und versucht, sie neu zu erstellen

Nichts funktioniert für mich.

Ich vermute, dass die Wurzeln des Problems in den Beziehungen sind, aber ich nur auf die Id Felder beziehen (dies scheint keine Population der Navigation Property des zugehörigen Modells auszulösen - warum verursacht dies ein Problem?) Was? Ich weiß nicht, ob ich die Objekte nicht richtig speichere oder ob das Design der Objekte nicht richtig ist. Wenn ich Entitäten (einschließlich der Definition ihrer Beziehungen) über Controller speichere, findet die Duplizierung nicht statt.

Die Entitäten und ihre Beziehungen sind relativ einfach:

public class Org : BaseEntity, IEntityBase 
    { 
     public string Name { get; set; } 
     public List<Portfolio> Portfolios { get; set; } 

    } 

public class Portfolio : BaseEntity, IEntityBase 
    { 
     public string Name { get; set; } 

     public int OrganizationId { get; set; } 
     [ForeignKey("OrganizationId")] 
     public virtual Org Organization { get; set; } 

     public bool IsPrivate { get; set; } 
     public List<Project> Projects {get;set;} 
    } 
} 

public class Project : BaseEntity, IEntityBase 
    { 
     public string Name { get; set; } 
     public int PortfolioId { get; set; } 
     [ForeignKey("PortfolioId")] 
     public Portfolio Portfolio { get; set; } 
    } 

Update: ich verschiedene Dinge versucht, diese reparieren zu lassen, darunter:

Aufruf _cont.SaveChanges() jedes Mal ein Objekt dbSet hinzugefügt wird:

Org o = OrgToken.ToObject<Org>(); 
_cont.Orgs.Add(o); 
_cont.SaveChanges(); 

Abrufen eines gespeicherten Objekts aus der Datenbank zum Erstellen der Beziehung:

Portfolio p = PortfolioToken.ToObject<Portfolio>(); 
p.OrganizationId = _cont.Orgs.Find(o.Id).Id; 
_cont.Portfolios.Add(p); 
_cont.SaveChanges(); 

oder

Portfolio p = PortfolioToken.ToObject<Portfolio>(); 
p.Organization = _cont.Orgs.Find(o.Id); 
_cont.Portfolios.Add(p); 
_cont.SaveChanges(); 

oder

Portfolio p = PortfolioToken.ToObject<Portfolio>(); 
p.Organization = _cont.Find<Org>(p.id); 
_cont.Portfolios.Add(p); 
_cont.SaveChanges(); 

Mein Kontext ist nichts Besonderes, ich glaube nicht, dass es etwas gibt, dass es auswirken könnte:

public class CoreContext : DbContext 
{ 
    public DbSet<Org> Orgs { get; set; } 
    public DbSet<Portfolio> Portfolios { get; set; } 
    public DbSet<Project> Projects { get; set; } 
    public DbSet<Metric> Metrics { get; set; } 
    public DbSet<OrgAccess> OrgAccess { get; set; } 

    public CoreContext(DbContextOptions<CoreContext> options) : base(options) { } 
    protected override void OnModelCreating(ModelBuilder modelBuilder) 
     { 
      foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys())) 
      { 
       relationship.DeleteBehavior = DeleteBehavior.Restrict; 
      } 

      modelBuilder.Entity<Org>().ToTable("Org").HasIndex(c=>c.Name).IsUnique(); 
      modelBuilder.Entity<Portfolio>().ToTable("Portfolio").HasOne(a => a.Organization); 
      modelBuilder.Entity<Project>().ToTable("Project"); 
     } 
    } 
} 
+0

sein State Management der Graphen, da sie nicht weiß, wie die Ansätze der Org (s) zu handhaben, keine der Orgs tatsächlich Holen Sie sich Ids, bis sie mit einem 'SaveChanges()' in die Datenbank geschoben werden, was Sie nie in der ersten Schleife tun, bevor Sie in die Portfolios springen. Wenn es eine ID gibt, würde ich überrascht sein. Das gleiche gilt für Portfolios zu Projekten, glaube ich. – mvermef

+0

Ich habe versucht, Änderungen zu speichern, sobald ein Objekt hinzugefügt wurde - keine Heilung – abolotnov

+0

Warum fügt Entity Framework vorhandene Objekte in meine Datenbank ein? http://msdn.microsoft.com/en-us/magazine/dn166926.aspx – Colin

Antwort

2

Das Problem hat nichts mit dem Ent zu tun ityFramework oder der Kontext oder die Datenbank. Das Problem besteht darin, wie der JSON-Mapper von Newtonsoft funktioniert.Nicht, dass es ein Problem ist, aber es ist völlig unerwartet, dass beim Konvertieren eines Teils der JSON-Datei .ToObject<T>() zugrundeliegende Objekte (ich nehme an) wenn ihre Namenskonvertierungen Beziehung zwischen Objektklassen übereinstimmen. Es tat dies für Portfolio und Project, aber tat dies nicht für die Users Sammlung, da es keine Beziehung zwischen den Modellen gibt.

Ich wünschte es wäre nicht so implizit, aber es ist was es ist. Ich teile das nur für den Fall, dass jemand in diese Schwierigkeiten gerät.

Der resultierende Code müßte wie folgt aussehen:

public void CreateOrgStructure(string path = "/Test/TestData.json"){ 
     string DataFilePath = AppContext.BaseDirectory + path; 
     JObject json = JObject.Parse(File.ReadAllText(DataFilePath)); 
     foreach (JToken OrgToken in json["Orgs"]) 
      { 
       Debug.WriteLine("Org "+OrgToken["Name"]); 
       Org o = OrgToken.ToObject<Org>(); 
       _cont.Orgs.Add(o); 
       _cont.SaveChanges(); 
     } 
} 
Verwandte Themen