Verwenden automapper zum aktualisieren eines Entity Framework-Entity

Ich versuche, mit Entity Framework und haben Automapper update meiner Person aus meinem Vertrag.

Mein code sieht wie folgt aus:

var temp = OrderContract;
Order order = dataAccess.FindOne<Order>(x => x.OrderId == temp.OrderId) 
              ?? new Order();

Mapper.Map(OrderContract, order);

if (order.OrderId <= 0)
   dataAccess.Add(order);

(Hinweis: ich bin mit dem Repository-Pattern. dataAccess.FindOne Anrufe CreateQuery Rückkehr eine Einheit.)

Das problem, das ich habe, ist mit den Beziehungen. Ich bekomme diese Fehlermeldung wenn ich ein update (Einsätze gut funktionieren):

Den Betrieb failed: Die Verbindung konnte nicht geändert werden, weil eine oder mehrere der foreign-key-Eigenschaften ist nicht auf null gesetzt werden. Wenn eine änderung vorgenommen wird, um eine Beziehung, die im Zusammenhang foreign-key-Eigenschaft ist festgelegt auf einen null-Wert. Wenn die foreign key nicht unterstützt null-Werte, eine neue Beziehung definiert werden müssen, die foreign-key-Eigenschaft zugewiesen werden muss, eine weitere nicht-null-Wert, oder den unabhängigen Objekt gelöscht werden müssen.

Ich vermute, dass automapper nicht aktualisieren, wie ich will, es zu. Aus der Fehlermeldung googeln und herum ich habe vermutet, dass meine Beziehungen, sind Sammlungen (und vielleicht auch diejenigen, die sich nicht Sammlungen) werden neu erstellt durch Automapper.

Wie kann ich feststellen, Automapper, um nur aktualisieren und nicht remake Objekte oder Sammlungen?

Vermutungen:

Habe ich gelesen, dass ich vielleicht brauchen, um die Nutzung UseDestinationValue option für automapper. Ich ging zurück und legte es an alle meine Sammlungen, Aber wenn ich das Tue, dann meine Einsätze scheitern mit einer foreign key-Verletzung.

Code-Zuordnungen:

Mit UseDestinationValue nur auf eine Sammlung (dieses fügt jedoch nicht aktualisiert):

//+ Source
Mapper.CreateMap<SourceContract, Source>()
    .IgnoreAllNonExisting();

//+ SelectedRequirement
Mapper.CreateMap<SelectedRequirementContract, SelectedRequirement>()
    .ForMember(x => x.SelectedRequirementId, opt => opt.MapFrom(src => src.RequirementId))
    .IgnoreAllNonExisting();

//+ Comment Contract
Mapper.CreateMap<CommentContract, Comment>()
    .ForMember(x => x.CommentText, opt => opt.MapFrom(src => src.Comment))
    .IgnoreAllNonExisting();

//+ Order Automapper setup
Mapper.CreateMap<OrderContract, Order>()
    .ForMember(x => x.Source, opt => opt.MapFrom(src => src.Source))
    .ForMember(x => x.Comment, opt => opt.MapFrom(src => src.Comment))
    //Although a mapping was created for Comment entity,
    //we still need to map the CommentId of the Order entity otherwise it will remain null during an update.
    //Another way to handle this would be to Delete CommentId from the Order entity.
    //However, if anyone updates (Update from model) OrderDataModel.edmx that property would show up again thus causing
    //a null value to be inserted during an update.
    .ForMember(x => x.CommentId, opt => opt.MapFrom(src => src.Comment.CommentId))
    .ForMember(x => x.SelectedRequirements, opt => {opt.UseDestinationValue(); opt.MapFrom(src => src.Requirements);})
    .ForMember(x => x.OrderStateId, opt => opt.MapFrom(src => src.StateId))
    .ForMember(x => x.OrderStateId, opt => opt.MapFrom(src => src.StateId))
    .IgnoreAllNonExisting();

Mit UseDestinationValue überall (hier nicht einfügen):

//+ Source
Mapper.CreateMap<SourceContract, Source>()
    .IgnoreAllNonExisting();

//+ SelectedRequirement
Mapper.CreateMap<SelectedRequirementContract, SelectedRequirement>()
    .ForMember(x => x.SelectedRequirementId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.RequirementId); })
    .IgnoreAllNonExisting();

//+ Comment Contract
Mapper.CreateMap<CommentContract, Comment>()
    .ForMember(x => x.CommentText, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment); })
    .IgnoreAllNonExisting();

//+ Order Automapper setup
Mapper.CreateMap<OrderContract, Order>()
    .ForMember(x => x.Source, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Source); })
    .ForMember(x => x.Comment, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment); })
    //Although a mapping was created for Comment entity,
    //we still need to map the CommentId of the Order entity otherwise it will remain null during an update.
    //Another way to handle this would be to Delete CommentId from the Order entity.
    //However, if anyone updates (Update from model) OrderDataModel.edmx that property would show up again thus causing
    //a null value to be inserted during an update.
    .ForMember(x => x.CommentId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment.CommentId); })
    .ForMember(x => x.SelectedRequirements, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Requirements); })
    .ForMember(x => x.OrderStateId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.StateId); })
    .ForMember(x => x.OrderStateId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.StateId); })
    .IgnoreAllNonExisting();

Was ich tun muss, so kann ich die insert-und update?

  • können Sie zeigen Sie Ihre Order und OrderContract Klassen?
  • mein Vertrag kann hier eingesehen werden: raw.github.com/gist/1296415/.... Die Order-Klasse, ist ein entity-Objekt und ist sehr groß. Ich würde das eher nicht machen es vorzeigbar ist, es sei denn, es gibt einen klaren Grund, wie es hilfreich wäre.
  • Haben Sie dieses Problem behoben? Ich habe das gleiche problem.
  • AutoMapper nicht Zusammenführen, es schafft neue. Wenn Sie Zusammenführen möchten, dann verwenden Sie nicht AutoMapper und schreiben Sie Ihre eigene ein -> b-mapping-Methode.
  • AutoMapper kann beides tun. Mapper.Map(sourceObject, destObject)
  • Nicht Zusammenführen von zwei Objekten, die die Eigenschaften im Quell-Objekt und erzeugt eine neue Instanz von destObject mit den Werten aus sourceObject. Es nicht zusammenfassen.
  • Von dem, was ich gesehen habe, es nicht eine neue Instanz. Es hält die gleiche Instanz und schreibt über alle zugeordneten Eigenschaften, die nicht ignorieren gesetzt. Alle Eigenschaften, die nicht zugeordnet werden allein gelassen. Hier ist eine Zusammenfassung, die zeigt, dass AutoMapper aktualisieren einer vorhandenen Instanz, wobei einige der Werte, die von einem Quellobjekt (Zusammenführen). Diese läuft in LinqPad mit automapper installiert: gist.github.com/Vaccano/6324223
  • ok...wenn die Eigenschaft wird ignoriert, dann nicht, dass die Niederlage der Zweck der Zusammenführung?? Wenn eine Eigenschaft wird ignoriert, es wird ein null-Wert, nicht wahr?
  • Wie gesagt, es kann beides tun. Wenn Sie einen Seriendruck in ein vorhandenes Objekt, dann bekommt es den Wert, das wurde bereits im bestehenden Objekt. Wenn Sie eine neue erstellen, dann wäre es der Standard für den Typ des Objekts (null für Referenztypen). Wenn Sie das Beispiel habe ich gezeigt, Sie werden sehen, es hält den Wert, der in das vorhandene Objekt, anstatt bei null.
  • Können Sie fügen Sie den link für Ihre Einheiten wieder? Der link funktioniert nicht.

InformationsquelleAutor Vaccano | 2011-10-18
Schreibe einen Kommentar