Podczas korzystania z metody WithParameter instancja parametru będzie taka sama dla każdego rozstrzygniętego obiektu. Tak więc z .WithParameter("context", new PcpContext())
efektywnie używasz tego samego wystąpienia klasy PcpContext dla dowolnego rozwiązanego wystąpienia IRepository.
Przy obecnym kodzie, po usunięciu instancji IRepository, będzie ona również usuwać tę instancję PcpContext. Następnie każda kolejna próba rozwiązania IRepository otrzyma instancję PcpContext, która została usunięta. Potrzebujesz sposobu na otrzymanie nowego, świeżego egzemplarza DbContext EF na każdym Żądaniu HTTP, które jest usuwane na końcu żądania.
Jedną z opcji może być zarejestrowanie blok kodu dla IRepository tak że blok kodu jest wykonywana za każdym razem, gdy IRepository musi zostać rozwiązany:
_builder.Register<IRepository>(c => new EfRepository(new PcpContext()))
Lepszym rozwiązaniem byłoby stworzenie nowego IDatabaseContext
abstrakcji, aktualizowanie EfRepository
, więc zależy to od nowej abstrakcji IDatabaseContext zamiast klasy PcpContext
(co może już mieć miejsce :)).
Klasa implementacji dla IDatabaseContext będzie twoją klasą PcpContext, która musi dziedziczyć z EF DbContext i prawdopodobnie odbierać ciąg połączenia jako parametr.
public class EfRepository : IRepository
{
private readonly IDatabaseContext _context;
public EfRepository(IDatabaseContext context)
{
_context = context;
}
...methods for add, delete, update entities
//There is no longer need for this to be disposable.
//The disaposable object is the database context, and Autofac will take care of it
//public void Dispose()
}
public interface IDatabaseContext : IDisposable
{
... declare methods for add, delete, update entities
}
public class PcpContext: DbContext, IDatabaseContext
{
public EntityFrameworkContext(string connectionString)
: base(connectionString)
{
}
...methods exposing EF for add, delete, update entities
//No need to implement IDisposable as we inherit from DbContext
//that already implements it and we don´t introduce new resources that should be disposed of
}
Jest to lepsze dzięki pomysłowi wykorzystania kontenera IoC i pozostawienia im ciężaru zarządzania na całe życie. Teraz twoja klasa Repository nie musi być jednorazowa, ani też nie może zarządzać i pozbywać się zależności IDatabaseContext. To Autofac będzie śledził instancję kontekstu i usuwał ją w razie potrzeby.
Z tego samego powodu prawdopodobnie będziesz chciał użyć InstancePerLifetimeScope z zależnościami kontekstu bazy danych. Oznaczałoby to, że ten sam kontekst EF jest współdzielony dla każdej instancji repozytorium na tym samym żądaniu Http i jest usuwany na końcu żądania.
_builder.RegisterType<EfRepository>()
.As<IRepository>();
_builder.RegisterType<PcpContext>()
.As<IDatabaseContext>()
.WithParameter("connectionString", "NameOfConnStringInWebConfig")
.InstancePerLifetimeScope();
NIGDY nie przesyłaj naszego DbContext do dyspozycji. Dispose zostanie wywołany w przypadku wyjątku, ale nie chcesz zapisywać żadnych zmian, kiedy to się stanie. – Steven
@Steven: Usunąłem tę linię, w każdym razie nie rozwiązuje to problemu. – user1260827
Za każdym razem, gdy widziałem SaveChanges wewnątrz dispose, programista miał problemy. Zamierzam jeszcze zrozumieć, jaki wzorzec projektu sugeruje lub poleca "zatwierdza" lub "zapisuje" w Dispose. Zamierzam zasugerować, abyś ponownie ocenił plan, aby zapisać w środku. A co z obsługą błędów. dlaczego kojarzysz "zatwierdzanie" zmian z bazą danych ze zbiorem śmieci? Warto przeczytać http://msdn.microsoft.com/en-us/library/fs2xkftw%28VS.80%29.aspx Kiedy uruchamiasz dispose? może zacznij tutaj: http://stackoverflow.com/questions/898828/c-sharp-finalize-dispose-pattern –