Mam problem z Entity Framework w Asp.net. Chcę uzyskać wartość Id za każdym razem, gdy dodam obiekt do bazy danych. W jaki sposób mogę to zrobić?
SaveChanges
od razu, aby uzyskać identyfikator. Więcej informacji tutaj .
Mam problem z Entity Framework w Asp.net. Chcę uzyskać wartość Id za każdym razem, gdy dodam obiekt do bazy danych. W jaki sposób mogę to zrobić?
SaveChanges
od razu, aby uzyskać identyfikator. Więcej informacji tutaj .
Odpowiedzi:
To całkiem proste. Jeśli używasz DB wygenerowane identyfikatory (jak IDENTITY
w MS SQL) wystarczy dodać jednostce ObjectSet
i SaveChanges
na związane ObjectContext
. Id
zostaną automatycznie wypełnione dla Ciebie:
using (var context = new MyContext())
{
context.MyEntities.Add(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Yes it's here
}
Entity Framework domyślnie następujące każda INSERT
ze SELECT SCOPE_IDENTITY()
gdy auto generowane Id
są wykorzystywane s.
Korzystałem z odpowiedzi Ladislava Mrnki, aby z powodzeniem odzyskać ID podczas korzystania z Entity Framework, ale piszę tutaj, ponieważ nie wykorzystałem go (tj. Nie wykorzystałem go) i pomyślałem, że opublikuję tutaj moje odkrycia w na wypadek, gdyby ludzie chcieli „rozwiązać” problem, który miałem.
Rozważ obiekt zamówienia, który ma relację klucza obcego z klientem. Kiedy jednocześnie dodałem nowego klienta i nowe zamówienie, robiłem coś takiego;
var customer = new Customer(); //no Id yet;
var order = new Order(); //requires Customer.Id to link it to customer;
context.Customers.Add(customer);
context.SaveChanges();//this generates the Id for customer
order.CustomerId = customer.Id;//finally I can set the Id
Jednak w moim przypadku nie było to wymagane, ponieważ miałem relację klucza obcego między klientem i identyfikatorem zamówienia a klientem
Musiałem tylko to;
var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer};
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order
Teraz, gdy zapiszę zmiany, identyfikator generowany dla klienta jest również dodawany do zamówienia. Nie potrzebuję dodatkowych kroków
Wiem, że to nie odpowiada na pierwotne pytanie, ale pomyślałem, że może to pomóc programistom, którzy są nowicjuszami w EF, nadużywać najczęściej głosowanej odpowiedzi na coś, co może nie być wymagane.
Oznacza to również, że aktualizacje są ukończone w ramach jednej transakcji, potencjalnie unikając danych orphin (albo wszystkie aktualizacje są ukończone, albo żadna nie).
Musisz ponownie załadować encję po zapisaniu zmian. Ponieważ został zmieniony przez wyzwalacz bazy danych, którego EF nie może śledzić. Więc musimy ponownie załadować byt z bazy danych,
db.Entry(MyNewObject).GetDatabaseValues();
Następnie
int id = myNewObject.Id;
Spójrz na odpowiedź @jayantha w poniższym pytaniu:
Jak mogę uzyskać identyfikator wstawionego obiektu w strukturze Entity, gdy używasz defaultValue?
Pomocna może być odpowiedź @christian w poniższym pytaniu:
.GetDatabaseValues();
jeśli właśnie zapisałeś swój model w bazie danych. Identyfikator powinien zostać automatycznie ponownie wypełniony do modelu.
GetDatabaseValues()
gdyby nie znała identyfikatora obiektu, którego ma szukać w bazie danych?
Proszę odnieść się do tego linku.
http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/
Musisz ustawić właściwość StoreGeneratedPattern na tożsamość, a następnie wypróbować własny kod.
Możesz też tego użyć.
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Your Identity column ID
}
StoreGeneratedPattern
był dla mnie brakującym elementem.
Możesz uzyskać identyfikator dopiero po zapisaniu, zamiast tego możesz utworzyć nowego Guida i przypisać go przed zapisaniem.
Natrafiam na sytuację, w której muszę wstawić dane do bazy danych i jednocześnie wymagać podstawowego identyfikatora za pomocą struktury encji. Rozwiązanie :
long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
{
InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
InfoBase.Add(generalinfo);
InfoBase.Context.SaveChanges();
id = entityclassobj.ID;
return id;
}
Wszystkie odpowiedzi są bardzo dobrze dostosowane do ich własnych scenariuszy, co zrobiłem inaczej, to to, że przypisałem int PK bezpośrednio z obiektu (TEntity), który Add () zwrócił do zmiennej int takiej jak ta;
using (Entities entities = new Entities())
{
int employeeId = entities.Employee.Add(new Employee
{
EmployeeName = employeeComplexModel.EmployeeName,
EmployeeCreatedDate = DateTime.Now,
EmployeeUpdatedDate = DateTime.Now,
EmployeeStatus = true
}).EmployeeId;
//...use id for other work
}
więc zamiast tworzyć cały nowy obiekt, po prostu bierz co chcesz :)
EDYCJA Dla pana @GertArnold:
Add
(jeśli tak jest DbSet.Add
) magicznie nie przypisuje wartości EmployeeId
.
SaveChanges
. Niemożliwy. Chyba że masz jakiś inny proces, który przypisuje EmployeeId
, na przykład w Employee
konstruktorze. LUB używasz EF core ForSqlServerUseSequenceHiLo
. W każdym razie nie dajesz całego obrazu.
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;
To zadziała.
Repository
jest, co jest. A „to zadziała” to jakieś wyjaśnienie!
Istnieją dwie strategie:
Użyj wygenerowanej przez bazę danych ID
( int
lub GUID
)
Cons:
Powinieneś wykonać, SaveChanges()
aby uzyskać ID
tylko zapisane elementy.
Plusy:
Może używać int
tożsamości.
Użyj wygenerowanego przez klienta ID
- tylko GUID.
Plusy: minimalizacja SaveChanges
operacji. Możliwość wstawienia dużego wykresu nowych obiektów na jedną operację.
Cons:
Dozwolone tylko dla GUID
Przy pierwszym użyciu kodu EF 6.x.
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
i zainicjuje tabelę bazy danych, umieści ona
(newsequentialid())
wewnątrz właściwości tabeli pod nagłówkiem Wartość domyślna lub Powiązanie, umożliwiając zapełnianie identyfikatora podczas wstawiania.
Problem polega na tym, że tworzysz tabelę i dodajesz
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
część później, przyszłe aktualizacje baz danych nie dodają ponownie (newsequentialid ())
Poprawnym sposobem jest wyczyszczenie migracji, usunięcie bazy danych i ponowna migracja ... lub możesz po prostu dodać (newsequentialid ()) do projektanta tabel.
when -column- is NULL, then NEWID()