web-dev-qa-db-de.com

Verspotten oder vortäuschen von DbEntityEntry oder Erstellen eines neuen DbEntityEntry

Nach meiner anderen Frage zum Verspotten von DbContext.Set habe ich noch eine Frage zum Verspotten von EF Code First.

Ich habe jetzt eine Methode für mein Update, die so aussieht:

if (entity == null)
    throw new ArgumentNullException("entity");

Context.GetIDbSet<T>().Attach(entity);
Context.Entry(entity).State = EntityState.Modified;
Context.CommitChanges();

return entity;

Context ist eine Schnittstelle meines eigenen DbContext.

Das Problem, auf das ich stoße, ist, wie ich mit dem umgehen soll

Context.Entry(entity).State.

Ich habe diesen Code schrittweise durchgearbeitet und er funktioniert, wenn ich einen echten DbContext als Implementierung meiner Context-Schnittstelle habe. Aber wenn ich meinen falschen Kontext dort platziere, weiß ich nicht, wie ich damit umgehen soll.

Es gibt keinen Konstruktor für eine DbEntityEntry-Klasse, daher kann ich in meinem falschen Kontext nicht einfach einen neuen erstellen.

Hat jemand Erfolg damit gehabt, DbEntityEntry in Ihren CodeFirst-Lösungen zu verspotten oder zu fälschen?

Oder gibt es eine bessere Möglichkeit, mit den Zustandsänderungen umzugehen?

59
taylonr

Genau wie im anderen Fall müssen Sie eine zusätzliche Ebene der Indirektion hinzufügen:

interface ISalesContext
{
    IDbSet<T> GetIDbSet<T>();
    void SetModified(object entity)
}

class SalesContext : DbContext, ISalesContext
{
    public IDbSet<T> GetIDbSet<T>()
    {
        return Set<T>();
    }

    public void SetModified(object entity)
    {
        Entry(entity).State = EntityState.Modified;
    }
}

Statt die Implementierung aufzurufen, rufen Sie einfach SetModified auf.

91
Diego Mijelshon

Ich habe diese Frage gefunden, als ich mit Moq einen Unit-Test durchführen musste, keine eigene Schnittstelle. Ich wollte bestimmte Felder so einstellen, dass sie nicht geändert wurden, aber die Methode SetModified kann auch mit dem Objekt verwendet werden. 

DbContext:

public class AppDbContext : DbContext
{   
    ...
    public virtual void SetModified(GuidEntityBase entity)
    {
        Entry(entity).State = EntityState.Modified;
        Entry(entity).Property(x => x.CreatedDate).IsModified = false;
        Entry(entity).Property(x => x.CreatedBy).IsModified = false;
    }
    ...
}

Prüfung:

var mockContext = new Mock<AppDbContext>();
mockContext.Setup(c => c.MyDbSet).Returns(mockMyDbSet.Object);
mockContext.Setup(c => c.SetModified(It.IsAny<GuidEntityBase>()));
0
Ogglas