2008-11-18 2 views
7

Ok gut Ich habe versucht, mein Modell zu LINQ zu konvertieren, wollte aber nicht meine aktuellen DTOs und ihre Schnittstellen, die verstreut sind wegwerfen die Domäne.Hilfe benötigt für LINQ zu SQL-Operationen (einfügen/aktualisieren) mit verschachtelten POCOs

ich es geschafft, dieses Blog-Post zu finden, die den Prozess recht gut umrissen hat:

Achieving POCOs in LINQ To SQL

Ich habe die das Abrufen von Datensätzen, um Objekte zu bekommen gut funktionierten, aber geschafft, aufgrund der verschachtelten Natur von meinem meinem Modell, kann ich nicht scheinen, dass ich zusätzlich für die Kinderobjekte arbeite. Das heißt, wenn ich ein untergeordnetes Objekt erzeuge und den Verweis auf das gewünschte Eltern-Objekt festlege, löst LINQ to SQL immer noch eine Ausnahme aus, die angibt, dass der Verweis des Kindes auf das übergeordnete Objekt NULL ist. Wenn ich ein einfaches altes übergeordnetes Objekt hinzuzufügen versuche, gelingt es, aber das Hinzufügen untergeordnete Objekte nicht direkt

Hier ist mein Fehler Test:

[Test] 
    public void AddSelectionShouldAddSelectionToMarket() 
    { 
     Market market = (Market) new Repository().GetMarket(1); 

     Selection selection = new Selection(); 
     selection.Market = market; 

     new Repository().AddSelection(selection); 

     Assert.IsTrue(selection.SID > 0); 
    } 

Hier ist die Fehlermeldung:

System.InvalidOperationException : Es wurde versucht, eine Beziehung zwischen einem Markt und einer Auswahl zu entfernen. Einer der Fremdschlüssel der Beziehung (Selection.MID) kann jedoch nicht auf null festgelegt werden.

Die relevanten Teile der zwei Objekte:

[DataContract] 
public class Selection : ISelection 
{ 
    private int mID; 
    [DataMember] 
    public int MID 
    { 
     get { return this.mID; } 
     set { this.mID = value; } 
    } 

    private Market market; 
    [DataMember] 
    public Market Market 
    { 
     get { return this.market; } 
     set 
     { 
      this.market = value; 
      this.mID = value.MID; 
     } 
    } 
} 

[DataContract] 
public class Market : IMarket 
{ 
    private int mID; 
    [DataMember] 
    public int MID 
    { 
     get { return this.mID; } 
     protected set { this.mID = value; } 
    } 

    private List<Selection> selections; 
    [DataMember] 
    public List<Selection> Selections 
    { 
     get { return this.selections; } 
     set 
     { 
      this.selections = value; 
      // For LINQ 
      foreach (Selection selection in selections) 
      { 
       selection.MID = mID; 
       selection.Market = this; 
      } 
     } 
    } 
} 

Mein DA-Code:

 MarketsDataContext context = new MarketsDataContext(); 

     DataLoadOptions options = new DataLoadOptions(); 
     options.LoadWith<Selection>(s => s.Prices); 
     options.LoadWith<Market>(m => m.Selections); 

     context.LoadOptions = options; 
     return context; 

und;

public void AddSelection(ISelection selection) 
    { 
     using (MarketsDataContext context = MarketsDataContext.GetContext()) 
     { 
      context.Selections.InsertOnSubmit((Selection) selection); 
      context.SubmitChanges(); 
     } 
    } 

Und meine XML-Mapping schließlich:

<Table Name="dbo.Markets" Member="Markets"> 
    <Type Name="Market"> 
     <Column Name="MID" Member="MID" Storage="mID" DbType="Int NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> 
     <Association Name="FK_Market-Selections" Member="Selections" Storage="selections" ThisKey="MID" OtherKey="MID" DeleteRule="NO ACTION" /> 
    </Type> 
    </Table> 

    <Table Name="dbo.Selections" Member="Selections"> 
    <Type Name="Selection"> 
     <Column Name="SID" Member="SID" Storage="sID" DbType="Int NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> 
     <Column Name="MID" Member="MID" Storage="mID" DbType="Int NOT NULL" /> 
     <Association Name="FK_Market-Selections" Member="Market" Storage="market" ThisKey="MID" OtherKey="MID" IsForeignKey="true" /> 
    </Type> 
    </Table> 

Also, kann mir jemand in die richtige Richtung? Ich habe stundenlang gesucht ...

Edit:

Hier ist mein Stacktrace für meine Testfehler:

at System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData() 
at System.Data.Linq.ChangeProcessor.ValidateAll(IEnumerable`1 list) 
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges() 
at BetMax.DataModel.Repository.AddSelection(ISelection selection) in Repository.cs: line 68 
at BetMax.DataModel.Test.ModelTest.AddSelectionShouldAddSelectionToMarket() in ModelTest.cs: line 65 

Und meine GetMarket Methode:

public IMarket GetMarket(int MID) 
    { 
     Market market; 
     using (MarketsDataContext context = MarketsDataContext.GetContext()) 
     { 
      market = context.Markets.Single(m => m.MID == MID); 
     } 
     return market; 
    } 

Edit 2:

Nun, Hinzufügen

zu Auswahlen Fremdschlüssel in der XML-Zuordnung hat den Fremdschlüsselfehler entfernt, aber jetzt bekomme ich einen Nullverweis auf eines der untergeordneten Objekte von Selections und sagt, sein Verweis auf Selection ist null, obwohl Selection initialisiert wird keine seiner Variablen gesetzt (außerhalb der Fremdschlüssel). Ich habe sogar versucht, ein Kind-Objekt erstellen, und legen Sie seine Referenzen richtig bin aber immer noch diesen Fehler:

System.NullReferenceException: Object reference not set to an instance of an object. 
at BetMax.DTO.Price.set_Selection(Selection value) in Price.cs: line 25 
at System.Data.Linq.Mapping.PropertyAccessor.Accessor`3.SetValue(ref T instance, V value) 
at System.Data.Linq.Mapping.MetaAccessor`2.SetBoxedValue(ref Object instance, Object value) 
at System.Data.Linq.ChangeProcessor.ClearForeignKeysHelper(MetaAssociation assoc, Object trackedInstance) 
at System.Data.Linq.ChangeProcessor.ClearForeignKeyReferences(TrackedObject to) 
at System.Data.Linq.ChangeProcessor.PostProcessUpdates(List`1 insertedItems, List`1 deletedItems) 
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges() 
at BetMax.DataModel.Repository.AddSelection(ISelection selection) in Repository.cs: line 68 
at BetMax.DataModel.Test.ModelTest.AddSelectionShouldAddSelectionToMarket() in ModelTest.cs: line 69 

Preis ist eine weitere Aufgabe, in derselben konstruiert, dass die Auswahl an Markt zusammenhängt (1 selection viele Preise hat, 1 Markt hat viele Auswahlmöglichkeiten) usw. usw.

Antwort

0

Ich würde vorschlagen, Ihren Code an Sidar Ok zu senden. Er ist ein netter Kerl und wird dich in die richtige Richtung weisen. Oder poste zumindest einen Kommentar zu seinem Blog, der ihn hier auf deine Frage hinweist.

4

Ich vermute, das Problem liegt in Ihrer Testmethode. Sie haben ein Repository mit einem DataContext erstellt, Sie haben jedoch ein anderes Repository erstellt.

[Test] 
public void AddSelectionShouldAddSelectionToMarket() 
{ 
    Market market = (Market) new Repository().GetMarket(1); 

    Selection selection = new Selection(); 
    selection.Market = market; 

    new Repository().AddSelection(selection); 

    Assert.IsTrue(selection.SID > 0); 
} 

Erstellen Sie ein Repository und verwenden Sie es in der Testmethode.

[Test] 
public void AddSelectionShouldAddSelectionToMarket() 
{ 
    Repository repository = new Repository(); 
    Market market = (Market) repository.GetMarket(1); 

    Selection selection = new Selection(); 
    selection.Market = market; 

    repository.AddSelection(selection); 

    Assert.IsTrue(selection.SID > 0); 
} 
+0

Ahh sehr guten Punkt. Ich werde den Kontext jedes Mal, wenn ich eine Operation mache, tatsächlich entsorgen, also werde ich sehen, ob es etwas länger dauert ... – mwjackson

+0

Nun, es sieht so aus, als hätte das Problem nicht gelöst. – mwjackson

2

Nur eine Vermutung, aber es könnte hier

public Market Market 
{ 
    get { return this.market; } 
    set 
    { 
     this.market = value; 
     this.mID = value.MID; 
    } 
} 

sein Was passiert, wenn der Wert, den Sie Markt gesetzt null ist? Die letzte Zeile davon ist ungültig, da sie null.MID nicht auflösen kann. Vielleicht müssen Sie dies für Ihre Setzer:

set 
    { 
     this.market = value; 
     this.mID = (value == null) ? null : value.MID; 
    } 

Auch würde Ihre MID nullable sein haben

int? MID 
+0

Nein, es sollte kein Problem sein (denke ich). Dies ist genau der Ansatz, den SidarOK im Blog postet ... – mwjackson

+0

Aber wie GeekyMonkey erwähnt, wird diese Kontrolle Ihre Klasse stabiler machen. Da Ihre Market-Eigenschaft offen ist, um null zu setzen, ist es kein Problem, zu prüfen, ob es null ist. –

+0

Aber halt an, ich möchte sicherstellen, dass die Fremdschlüsselfelder (zB MID in Selection) nicht Null sind ... Das Zulassen von Nullen könnte zu verwaisten Einträgen in der Datenbank führen. – mwjackson

2

Für Ihre neue Ausgabe; Das Problem tritt bei der Nullzuweisung der Auswahleigenschaft von Price auf. Hast du das mit deinem Code gemacht? Könntest du dem Code-Teil nochmal geben, dass du die Ausnahme bekommen hast? Ich meine Zuordnung zu Price-Entity ...

Bearbeiten Sie nach Kommentar: Ich denke, es ist wegen Nullsteuerausnahme, wie wir zuvor auf GeekyMonkeys post erwähnt. Bei der Initialisierung der Selection-Klasse muss die Price-Eigenschaft als null festgelegt werden, aber wenn null zugewiesen ist, wird null reference zurückgegeben. Sie müssen also eine Nullkontrolle in der Eigenschaft price durchführen.

private List<Price> prices 
[DataMember] 
public List<Price> Prices 
{ 
    get { return this.prices; } 
    set 
    { 
     if(value != null) 
     { 
      this.pricess = value; 
      // For LINQ    
      foreach (Price price in prices) 
      { 
      price.MID = mID; 
      price.Selection = this; 
      } 
     } 
    } 
} 
+0

Ich berühre momentan keine Preise. Alles, was ich im Moment versuche, ist, den obigen Test zu bestehen, der eine neue Auswahl (mit einer Null-Liste ) erstellt und zum Market-Objekt hinzufügt. Irgendwie wirft meine Konfiguration einen Nullrefehler, der von Price kommt? – mwjackson

+0

Ich bearbeite meinen Beitrag, siehe es. –

+0

Ok, ich werde es versuchen und dich wissen lassen, wie es mir geht. Danke noch einmal! – mwjackson

2

Ich weiß, es ist schon eine Weile, und Sie haben wahrscheinlich schon das Problem gelöst, aber vielleicht nicht ...

Ich gehe davon aus, dass Ihre Datenstruktur dieser ähnlich ist:

Market 
====== 
Market_ID  int not null identity (1, 1) 


Selection 
========= 
Selection_ID int not null identity (1, 1) 
Market_ID  int (FK to Market) 
Selection_Name varchar(50) 

um einen neuen Markt und eine neue Auswahl hinzufügen gleichzeitig:

Selection selection = new Selection(); 
Market market = new Market(); 

market.Selections.Add(selection); 
DataContext.Markets.InsertOnSubmit(market); 
DataContext.SubmitChanges(); 

um eine neue Auswahl zu einem exis hinzufügen ting Markt:

Selection selection = new Selection(); 
Market market = DataContext.Markets.Where(a => a.Market_ID == 7).Single(); 

market.Selections.Add(selection); 
DataContext.SubmitChanges(); 

die erste Auswahl in einem Markt zu aktualisieren:

Selection selection = DataContext.Markets.Where(a => a.Market_ID == 7).Selections.First(); 

selection.Selection_Name = "New Name"; 
DataContext.SubmitChanges();