verwendetes Datenbanksystem: MySql
Hallo,
ich benutze das EntityFramework von MS welches mir mittels TextTemplationg T4
meine classes erstellt.
MySql.Data.EntityFramework
Entity Framework 6 (EF6
Ich möchte gerne Entitäten speichern bei Abänderung von
wenigen values:
using (var db = new DbContext())
{
foreach(var newMember in members)
{
var member = new Member();
member = this.actualMember;
member.name = "change values";
//set null not allowed for unique id long
//member.id = null;
db.MemberActivations.Add(member);
}
db.SaveChanges();
//only one item saved
}
leider kann ich die ID nicht auf NULL setzten,
wie erstelle ich nun mehrere Datensätze ohne diese
komplett neu ohne unique ID zu erstellen?
Bitte in die EF Doku schauen, da steht sowas beschrieben.
So darfst Du keine Werte kopieren; Du musst die Eigenschaften einzeln zuweisen, weil EF die Runtime Objekte trackt.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo schorge,
in deinem Codebeispiel liegt das Problem daran, dass du nach dem Erzeugen mit new der Referenz jedoch "this.actualMember" zuweist. Somit fügst du jedes mal das gleiche Objekt hinzu.
Die EF Runtime erkennt das und speichert dann nur eines.
Wenn ich dich recht verstehe möchtest du Kopien von Objekten hinzufügen.
Das Kopieren (clonen) musst du selbst implementieren.
class Member
{
Member Clone()
{
return new Member
{
a = this.a,
b = this.b,
c = this.c
// ID hier nicht setzen
};
}
}
foreach(var newMember in members)
{
var member = this.actualMember.Clone();
member.name = "change values";
//set null not allowed for unique id long
//member.id = null;
db.MemberActivations.Add(member);
}
Runtime Object Clone() ist alles andere als eine gute Idee beim EF.
Daher hat EF eine extra Methode für das Klonen von Values
var values = db.Entry(oldEntity).CurrentValues.Clone();
var newEntity = ...
db.Entry(newEntity ).CurrentValues.SetValues(values);
newEntity.Id = 0;
oder
db.Entry(newEntity).CurrentValues.SetValues(oldEntity);
newEntity.Id = 0;
Oder man verwendet AutoMapper, wenn man sich die Tipparbeit sparen will.
Kommt halt drauf an, wie tief man klonen will. Daher hab ich auf die Docs verwiesen, da ist alles beschrieben.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Habe eine DbExtension, aber ID ist immernoch null
//-----------------
foreach(var newMember in members)
{
var member = this.actualMember.Clone();
member.name = "change values";
//set null not allowed for unique id long
//member.id = null;
db.MemberActivations.Set<members>().AddAndSetIdToNull(newmember, x => x.id);
}
db.MemberActivations.SaveChanges();
//-----------------
public static class DbSetExtensions
{
public static T AddAndSetIdToNull<T>(this DbSet<T> dbSet, T entity, Expression<Func<T, object>> predicate = null) where T : class, new()
{
var newEntitei = (T)Activator.CreateInstance(entity.GetType());
foreach (var property in entity.GetType().GetProperties())
{
PropertyInfo propertyS = newEntitei.GetType().GetProperty(property.Name);
var value = property.GetValue(entity, null);
var operType = ((UnaryExpression)predicate.Body).Operand;
var memberName = ((MemberExpression)operType).Member;
if (memberName != propertyS)
{
propertyS.SetValue(newEntitei, property.GetValue(entity, null), null);
}
}
//id is 0 :(
bool exists = false;
return !exists ? dbSet.Add(newEntitei) : null;
}
}
Und warum die Bastelei, wenn das schon eingebaut ist?
Schreibst da nen Haufen Reflection-Code (oder kopiert 😉 mit anfälligen Methoden wie Runtime-Clone, dabei ist das mit eingebauten Funktionen sauber in 2-3 Zeilen zu machen. 🤔
PS: null ist nicht der Indikator für einen nicht gesetzten Key bei long; sondern 0.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code