Entity Framework nicht aktualisieren von Daten bei der Verwendung von Repository-Muster

Ich bin mit dem repository und unit of work Pattern und dependency injection Zugriff auf die Datenbank mit entity framework 5 in meiner web-Anwendung. Ich habe eine User Klasse, von dem Entity Framework generiert eine Code-First-Datenbank.

public class User
{
    public Guid UserId { get; set; }
    public string UserName { get; set; }
              .
              .
              .
    public string LanguagePreference { get; set; }
    public virtual List<Role> Roles { get; set; }
    public virtual List<Branch> Branches { get; set; }

}

Ich habe eine UserService Klasse, die verwendet wird zum Hinzufügen oder Aktualisieren von Benutzern. Diese Klasse nimmt eine IUserUnitOfWork als parameter in den Konstruktor und die Einheit injiziert eine UserUnitOfwork. Die IUserUserOfWork enthält eine IRepository<User> eine IRepository<Location> und ein IRepository<Role>. Diese sind als Repository<T> durch die DI-bootstrapper. Die IUserUnitOfWork stellt die verschiedenen Repositories mit dem gleichen entity framework DbContext. Ich Tat dies, wie ich Probleme bei der Aktualisierung der viele-zu-viele-Beziehungen mit Bezug auf den Benutzer (Standorte und Rollen).

UserUnitOfWork:

   public IRepository<Branch> BranchRepository {get; set;}
   public IRepository<Role> RoleRepository { get; set; }
   public IRepository<User> UserRepository { get; set; }
   public DbContext Context { get; set; }

   public UserUnitOfWork(DbContext context, ITransientErrorDetectionStrategy errorDetectionStrategy,RetryStrategy retryStrategy )
   {
       Context = context;
       BranchRepository = new Repository<Branch>(context, errorDetectionStrategy, retryStrategy);
       RoleRepository = new Repository<Role>(context, errorDetectionStrategy, retryStrategy);
       UserRepository = new Repository<User>(context, errorDetectionStrategy, retryStrategy);
   }

Die Repository-Klasse verwendet dann Entity Framework 5, um den Zugriff auf die Datenbank.

Beispiel der Methode aus dem Repository.FirstOrDefault:

   public virtual T FirstOrDefault(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "")
    {
        T result = null;

        _retryPolicy.ExecuteAction(() =>
        {
            IQueryable<T> entities = GetHelper(filter, orderBy, includeProperties);

            result = entities.FirstOrDefault();
        });


        return result;
    }

Und Aktualisieren von Repository:

    public virtual void Update(T entity)
    {
        if (_dbContext.Entry(entity).State == System.Data.EntityState.Detached)
        {
            _dbContext.Set<T>().Attach(entity);
            _dbContext.Entry(entity).State = System.Data.EntityState.Modified;
        }
    }

Also mein problem ist jetzt, dass wenn ich ein update der Benutzer es korrekt aktualisiert die Daten in der Datenbank, und als ich auf log out und log in der ersten änderung funktioniert. Jedoch wenn ich das update erneut, und melden Sie sich und in die neue änderung nicht abgeholt, obwohl die Datenbank aktualisiert wird.

Ich fange an zu befürchten, dass der Ansatz, den ich genommen habe, ist falsch, kann mir jemand sagen, wie stellen Sie sicher, dass, wenn ich ein update Entity Framework erhalten immer die neueste version?

EDIT:

So, ich habe eine Anfrage Lifetime-Manager etwa so:

public class PerHttpRequestLifetimeManager : LifetimeManager
{
    private readonly object key = new object();

    public override object GetValue()
    {
        if (HttpContext.Current != null &&
            HttpContext.Current.Items.Contains(key))
            return HttpContext.Current.Items[key];
        else
            return null;
    }

    public override void RemoveValue()
    {
        if (HttpContext.Current != null)
            HttpContext.Current.Items.Remove(key);
    }

    public override void SetValue(object newValue)
    {
        if (HttpContext.Current != null)
            HttpContext.Current.Items[key] = newValue;
    }
}

In meine DI-bootstrapper ich nun meine setup-domain-Kontext wie folgt:

        container.RegisterType<DbContext, DomainContext>(new PerHttpRequestLifetimeManager());

Es immer noch nicht zu sein scheinen zu arbeiten, bin ich etwas fehlt, anderes oder gebe ich es falsch?

EDIT 2:

Nur auf die Architektur:

Wir haben eine MVC-Anwendung, die verwendet, Angular JS, um ajax-Aufrufe zu einer Web-Api-service-layer. Die Web-Api eine ISomethingService injiziert. Es ist diese ISomethingService, der die repositories injiziert. Würde es etwas Verwirrung für die PerHttpRequestLifetimeManager, da es sowohl eine MVC-und Web API-Projekt am laufen?

EDIT 3:

Ein Beispiel, wie ich das speichern der bearbeiteten Benutzer:

Haben wir eine UserModel Klasse, die verwendet wird für die Kommunikation zwischen dem ServiceLayer -> API -> UI layer und zurück. Die User Klasse die man erzeugt, die von Entity Framework code first. Die EditUser-Methode in der UserService nimmt in einem UserModel.

Ich dann user die _unitOfWork.UserRepository, um die entsprechenden Datenbank-Benutzer

var editedUser = _unitOfWork.UserRepository.FirstOrDefault(x => x.UserId == userModel.UserId); 

Ich die Felder zuordnen, aus dem userModel die editedUser und ich dann anrufen (in der UserService)

_unitOfWork.UserRepository.Update(editedUser)

und nach

_unitOfWork.Save()

DOCH NOCH EIN EDIT:

Also ich habe bearbeitet eine einfache Methode, die updates zu einem einzigen text-Feld für die user-Tabelle (Sprache). Ich explizit die dispose-Methode aufrufen, nachdem Sie das update, um sicherzustellen, ich bin die Entsorgung der Methode.

   public void SetUserLanguagePreference(Guid userId, string language)
    {
        var user = _unitOfWork.UserRepository.FirstOrDefault(x => x.UserId == userId);

        user.LanguagePreference = language;

        _unitOfWork.UserRepository.Update(user);
        _unitOfWork.Save();
        _unitOfWork.Dispose();
    }

UnitOfWork.Dispose() ruft die dispose-Methode des repositories und der Dbcontext

Die Datenbank richtig aktualisiert. Jedoch ist das Verhalten immer noch falsch. Wenn ich den Abmelden und in die erste ruft es den richtigen Wert. Wenn ich es erneut ändern und sich ausloggen und wieder ist es nicht aktualisieren. Das ist das Muster, bevor es das erste update, nachdem ich die log-out und in, aber wenn ich es wieder ändern, und melden Sie sich und in es nicht es abholen.

  • Es klingt wie dein Kontext ist nicht erschaffen/zerstört werden pro Anfrage. Wie ist Ihr Kontext instanziiert wird für die Einspritzung?
  • mit Einheit wie diesem: container.RegisterType<DbContext, DomainContext - >();
  • Fallen alle diese "UnitOfWork" und "Repository" und die Arbeit mit nackten EF. Es erspart Ihnen Tonnen von Kopfschmerzen und Ihr code wird am Ende überraschend einfach.
  • es ist ein bisschen spät für, dass ich denke, ich habe es während des gesamten Projekts mit keine Probleme bis jetzt.
  • Welche Technologie verwenden Sie für dependency injection? (Ninject, Unity, AutoFac...)
  • Ich bin mit Unity. War mit 2.x, aber bis jetzt bin ich versucht, ein upgrade auf 3
  • Sie wollen vielleicht betrachten Sie so etwas wie eine HttpRequestLifetimeManager.
  • Vielen Dank Erik, werde ich das prüfen
  • siehe mein edit oben
  • Wo rufst du die SaveChanges?
  • siehe mein edit oben

InformationsquelleAutor Neil | 2014-03-24
Schreibe einen Kommentar