Entity Framework i kontekst wywołania.usunąć()
Kiedy należy wywołać {[3] } z entity framework?
-
Czy ta wyimaginowana metoda jest zła?
public static string GetName(string userId) { var context = new DomainDbContext(); var userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId); context.Dispose(); return userName; }
-
Tak lepiej?
public static string GetName(string userId) { string userName; using(var context = new DomainDbContext()) { userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId); context.Dispose(); } return userName; }
-
Czy to jeszcze lepiej, to znaczy, jeśli nie nazwać kontekstu.Dispose () podczas używania using ()?
public static string GetName(string userId) { string userName; using(var context = new DomainDbContext()) { userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId); } return userName; }
6 answers
W rzeczywistości są to dwa pytania w jednym:
- Kiedy powinienem
Dispose()
z kontekstu? - Jaka powinna być długość życia mojego kontekstu?
Odpowiedzi:
Nigdy 1.
using
jest implicitDispose()
w blokutry-finally
. Oddzielna InstrukcjaDispose
może zostać pominięta, gdy wyjątek wystąpi wcześniej. Ponadto, w większości przypadków, nie wywołanieDispose
w ogóle (w sposób dorozumiany lub jawny) nie jest szkodliwy .Zobacz np. Entity Framework 4 - długość życia / zakres kontekstu w aplikacji winform . Krótko mówiąc: długość życia powinna być "krótka", statyczny kontekst jest zły.
1 jak niektórzy komentowali, wyjątek od tej reguły stanowi sytuacja, gdy kontekst jest częścią komponentu, który implementuje IDisposable
sam i dzieli swój cykl życia. W takim przypadku wywołałbyś context.Dispose()
w metodzie Dispose
komponentu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-16 20:22:12
Śledziłem kilka dobrych tutoriali do korzystania z EF i nie pozbywają się kontekstu.
Byłem trochę ciekaw tego i zauważyłem, że nawet szanowany Microsoft VIP nie pozbywa się kontekstu. Odkryłem, że nie musisz pozbywać się dbContext w normalnej sytuacji.
Jeśli chcesz więcej informacji, możesz przeczytać ten wpis na blogu , który podsumowuje dlaczego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-03 16:43:13
Jeszcze lepiej:
public static string GetName(string userId)
{
using (var context = new DomainDbContext()) {
return context.UserNameItems.FirstOrDefault(x => x.UserId == userId);
}
}
Nie ma potrzeby zwracania wyniku spoza zakresu using
; po prostu zwróć go natychmiast, a nadal uzyskasz pożądane zachowanie usuwania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-16 20:03:31
Możesz zdefiniować kontekst bazy danych jako pole klasy i zaimplementować IDisposable
. Coś jak poniżej:
public class MyCoolDBManager : IDisposable
{
// Define the context here.
private DomainDbContext _db;
// Constructor.
public MyCoolDBManager()
{
// Create a new instance of the context.
_db = new DomainDbContext();
}
// Your method.
public string GetName(string userId)
{
string userName = _db.UserNameItems.FirstOrDefault(x => x.UserId == userId);
return userName;
}
// Implement dispose method.
// NOTE: It is better to follow the Dispose pattern.
public void Dispose()
{
_db.dispose();
_db = null;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-31 12:28:04
Jak wspomniał Daniel, nie musisz pozbywać się dbContext.
Z Artykułu:
mimo że implementuje IDisposable, implementuje go tylko po to, aby można było nazwać Disposable jako zabezpieczenie w niektórych szczególnych przypadkach. Domyślnie DbContext automatycznie zarządza połączeniem.
Więc:
public static string GetName(string userId) =>
new DomainDbContext().UserNameItems.FirstOrDefault(x => x.UserId == userId);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-15 15:34:01
Można chcieć pozbyć się kontekstu w niektórych przypadkach.
W uproszczeniu przykładu OP wystarczy słowo kluczowe using
.
Więc kiedy musimy użyć dispose
?
Spójrz na ten scenariusz: musisz przetworzyć duży plik, komunikację lub umowę o świadczenie usług internetowych, która wygeneruje setki lub tysiące rekordów BD.
Dodawanie (+400) tysięcy lub setek encji w EF jest uciążliwe dla wydajności: kwestia wydajności w ramach encji, saveChanges jest bardzo wolno
Rozwiązanie jest opisane bardzo dobrze na tej stronie: https://entityframework.net/improve-ef-add-performance
TL; DR-zaimplementowałem to i tak skończyłem z czymś takim:
/// <summary>
/// Convert some object contract to DB records
/// </summary>
/// <param name="objs"></param>
public void SaveMyList(WCF.MyContract[] objs)
{
if (objs != null && objs.Any())
{
try
{
var context = new DomainDbContext();
try
{
int count = 0;
foreach (var obj in objs)
{
count++;
// Create\Populate your object here....
UserNameItems myEntity = new UserNameItems();
///bla bla bla
context.UserNameItems.Add(myEntity);
// https://entityframework.net/improve-ef-add-performance
if (count % 400 == 0)
{
context.SaveChanges();
context.Dispose();
System.Threading.Thread.Sleep(0); // let the system breathe, other processes might be waiting, this one is a big one, so dont use up 1 core for too long like a scumbag :D
context = new DomainDbContext();
}
}
context.SaveChanges();
}
finally
{
context.Dispose();
context = null;
}
Log.Info("End");
}
catch (Exception ex)
{
Log.Error(string.Format("{0}-{1}", "Ups! something went wrong :( ", ex.InnerException != null ? ex.InnerException.ToString() : ex.Message), ex);
throw ex;
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-11 11:47:41