Laden...

Wie kann ich die Id bei einem Entity Framework Entity auf NULL setzen?

Erstellt von schorge vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.503 Views
S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 4 Jahren
Wie kann ich die Id bei einem Entity Framework Entity auf NULL setzen?

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?

16.806 Beiträge seit 2008
vor 4 Jahren

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.

W
113 Beiträge seit 2006
vor 4 Jahren

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);
}

16.806 Beiträge seit 2008
vor 4 Jahren

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.

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 4 Jahren

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;
        }
    }

16.806 Beiträge seit 2008
vor 4 Jahren

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.

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 4 Jahren

@abt Danke, dann vergessen wir den Code mal schnell 😁