मैं इकाई ढांचे में सम्मिलित इकाई की आईडी कैसे प्राप्त कर सकता हूं? [बन्द है]


611

मुझे Asp.net में Entity फ्रेमवर्क की समस्या है। जब भी मैं डेटाबेस में कोई ऑब्जेक्ट जोड़ता हूं, मैं आईडी मान प्राप्त करना चाहता हूं। मैं यह कैसे कर सकता हूँ?


16
नीचे दिए गए लदिस्लाव मृणका का उत्तर सही उत्तर है, और इसे इस तरह स्वीकार किया जाना चाहिए।
सीएसहार्क

3
ओपी ने केवल एक बार अपने खाते से पोस्ट किया, यह प्रश्न अधिक विशिष्ट है। इसने उसे प्रतिष्ठा में लगभग 2k / (दिया!), उत्तर को स्वीकार नहीं किया गया क्योंकि उस दिन के बाद से खाता छोड़ दिया गया है।
मुरारीलेक्स

1
यदि आपको विदेशी कुंजी संबंध में इसका उपयोग करने के लिए बस आईडी की आवश्यकता है, तो आप इसके बजाय पूर्व में जोड़े गए इकाई के लिए अपने आश्रित इकाई की नेविगेशनल संपत्ति निर्धारित करने के बजाय विचार कर सकते हैं। इस तरह आपको SaveChangesसिर्फ आईडी प्राप्त करने के लिए तुरंत कॉल करने की आवश्यकता नहीं है । आगे यहां पढ़ रहे हैं
B12Toaster

एंटिटी फ्रेमवर्क कोर 3.0 के लिए, AcceptAllChangesOnSuccess पैरामीटर को सच के रूप में जोड़ें: इंतजार करें _context.SaveChangesAsync (सच);
माइक

जवाबों:


1005

यह बहुत आसान है। यदि आप DB उत्पन्न Ids (जैसे IDENTITYMS SQL में) का उपयोग कर रहे हैं, तो आपको बस संबंधित ObjectSetऔर उस SaveChangesपर इकाई जोड़ने की आवश्यकता है ObjectContextIdस्वचालित रूप से आपके लिए भर जाएगा:

using (var context = new MyContext())
{
  context.MyEntities.Add(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Yes it's here
}

इकाई की रूपरेखा डिफ़ॉल्ट रूप से प्रत्येक इस प्रकार INSERTके साथ SELECT SCOPE_IDENTITY()जब स्वत: जनरेट Idरों किया जाता है।


34
तो आप गलत सवाल पूछ रहे हैं। यदि आपको अपवाद के साथ कोई समस्या है, तो आपको अपना अपवाद (और आंतरिक अपवाद) दिखाते हुए प्रश्न पूछना चाहिए और उस त्रुटि का कारण कोड स्निपेट होना चाहिए।
लादिस्लाव मृंका

3
सुनिश्चित करें कि आप जो एंटिटी जोड़ रहे हैं, वह एक वैध एंटिटी है। उदाहरण के लिए, "नहीं नल" के डेटाबेस प्रतिबंध के साथ कुछ भी भरा जाना चाहिए आदि
प्रात:

4
@LadislavMrnka: नव-निर्मित वस्तु के नेविगेशन गुणों के बारे में क्या? वे परिवर्तनों को सहेजने के बाद स्वचालित रूप से आबाद नहीं हो रहे हैं।
इसहाक क्लेनमैन

4
आइए निम्न परिदृश्य पर विचार करें: तालिका 1 को तालिका 2 में उपयोग करने के लिए एक @@ पहचान उत्पन्न करना है। Table1 और table2 दोनों को एक ही लेन-देन में माना जाता है, उदाहरण के लिए, एक SaveChange ऑपरेशन को टेबल के दोनों डेटा को सहेजना होगा। @@ पहचान तब तक उत्पन्न नहीं होगी जब तक कि 'SaveChanges' को लागू न किया जाए। हम इस स्थिति को कैसे संबोधित कर सकते हैं?
अरश

7
@Djeroen: यदि आप डेटाबेस जनरेट किए गए Id का उपयोग करते हैं, तो आपको पहले उन ऑब्जेक्ट्स को डेटाबेस में सम्मिलित करना होगा। यदि आपको प्रविष्टि से पहले Ids की आवश्यकता है, तो आपको डेटा डालने से पहले अद्वितीय Ids प्राप्त करने के लिए अपने तर्क का निर्माण करना होगा और डेटाबेस में पहचान कॉलम का उपयोग नहीं करना चाहिए।
लादिस्लाव मृका

124

मैं लद्दिस्लाव मृका के जवाब का उपयोग तब सफलतापूर्वक कर रहा था जब आईडेंटिटी फ्रेमवर्क का उपयोग करते समय आईडीएस को फिर से प्राप्त करना था, क्योंकि मैं यहां पोस्ट कर रहा हूं क्योंकि मैं इसे मिस- यूज कर रहा था (अर्थात जहां इसकी आवश्यकता नहीं थी) और सोचा था कि मैं अपने निष्कर्षों को यहां पोस्ट करूंगा- यदि लोग मेरे पास मौजूद समस्या को "हल" करना चाहते हैं।

एक ऑर्डर ऑब्जेक्ट पर विचार करें जिसका ग्राहक के साथ विदेशी संबंध है। जब मैंने एक नया ग्राहक और एक नया आदेश जोड़ा उसी समय मैं कुछ ऐसा कर रहा था;

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

हालांकि मेरे मामले में यह आवश्यक नहीं था क्योंकि मेरे पास customer.Id और ऑर्डर के बीच एक विदेशी संबंध था

मुझे बस इतना ही करना था;

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

अब जब मैं परिवर्तनों को सहेजता हूं तो ग्राहक के लिए जो आईडी बनाई जाती है उसे भी ऑर्डर में जोड़ा जाता है। मुझे अतिरिक्त चरणों की कोई आवश्यकता नहीं है

मुझे पता है कि यह मूल प्रश्न का उत्तर नहीं देता है, लेकिन यह सोचा कि यह उन डेवलपरों की मदद कर सकता है जो किसी चीज की आवश्यकता के लिए शीर्ष-मतदान उत्तर का उपयोग करके ईएफ से नए हैं।

इसका अर्थ यह भी है कि एकल लेन-देन में पूर्ण रूप से अपडेट, संभावित रूप से ऑर्फ़िन डेटा से बचना (या तो सभी अपडेट पूर्ण, या कोई भी नहीं)।


8
धन्यवाद ! महत्वपूर्ण सर्वोत्तम अभ्यास टिप: var ऑर्डर = नया ऑर्डर {ग्राहक = ग्राहक}; यह संबंधित ऑब्जेक्ट को असाइन करने के लिए एंटिटी फ्रेमवर्क की शक्ति दिखाता है और आईडी स्वचालित रूप से अपडेट हो जाएगी।
ला गाय 88

इस अतिरिक्त जानकारी के उत्तर के लिए धन्यवाद। EF का उपयोग करते समय DB राउंडट्रिप को बचाने में बहुत मददगार था।
प्रसाद कोरहले

इस के लिए बहुत बहुत धन्यवाद। यही वह है जिसकी तलाश में मैं हूं। मेरा मानना ​​है कि "सेवचेंज" को दो बार कॉल करने से बेहतर तरीका हो सकता है
जोश

1
कृपया अपने उत्तर में भी उल्लेख करें (अधिमानतः मोटे अक्षरों में) यह एक व्यवहार व्यवहार का समाधान करता है। यदि कोई ऑब्जेक्ट जोड़ने में विफल है, तो लेनदेन का हिस्सा सफल नहीं होगा। जैसे व्यक्ति और छात्र को जोड़ना। व्यक्ति सफल होता है और छात्र असफल। अब व्यक्ति बेमानी है। हालांकि इस महान समाधान के लिए धन्यवाद!
इमरान फारुकी

32

परिवर्तनों को सहेजने के बाद आपको इकाई को फिर से लोड करना होगा। क्योंकि यह एक डेटाबेस ट्रिगर द्वारा बदल दिया गया है जिसे EF द्वारा ट्रैक नहीं किया जा सकता है। इसलिए हमें DB से इकाई को फिर से लोड करने की आवश्यकता है,

db.Entry(MyNewObject).GetDatabaseValues();

फिर

int id = myNewObject.Id;

नीचे दिए गए प्रश्न में @ संजय उत्तर देखें:

DefaultValue का उपयोग करते समय मैं इकाई इकाई में सम्मिलित इकाई का आईडी कैसे प्राप्त कर सकता हूं?

नीचे दिए गए प्रश्न में @christian उत्तर देखने से भी मदद मिल सकती है:

इकाई फ्रेमवर्क संदर्भ को ताज़ा करें?


2
नमस्ते, जब मैं ऐसा करता हूं, मुझे संकलन त्रुटि मिलती है जो कहता है: उदाहरण के लिए गुणों को हल नहीं कर सकते आईडी या नाम, क्या आप कृपया मदद कर सकते हैं?
मोर्टेजा अज़ीज़ी

1
@MortezaAzizi यह संभाला या अशक्त संपत्ति के मुद्दे की एक त्रुटि के लिए लगता है, लेकिन क्या आप कोड के कुछ स्निपेट को अधिक समझा या लिख ​​सकते हैं?
क्यूमास्टर

3
.GetDatabaseValues();अगर आपको सिर्फ अपना मॉडल डीबी में सहेजना है तो ऐसा नहीं करना चाहिए । आईडी को स्वचालित रूप से मॉडल को फिर से खोलना चाहिए।
vapcguy 23

3
@QMaster सिवाय इसके कि EF भी (और करता है) उसी SQL कथन को निष्पादित करता है और आपकी ऑब्जेक्ट की आईडी को पॉप्युलेट करता है। अन्यथा, यह एक ही समय में कई निर्भर वस्तुओं को बचाने में कैसे सक्षम है? GetDatabaseValues()अगर यह डेटाबेस में देखने के लिए ऑब्जेक्ट की आईडी नहीं जानता है तो यह कैसे कर पाएगा ?
क्रिलगर

2
@vapcguy मैं देख रहा हूं। अपने मातम के लिए धन्यवाद। मैं EF ASAP के दोनों संस्करणों में जाँच करूँगा।
QMaster

16

कृपया इस लिंक को देखें।

http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/

आपको StoreGeneratedPattern की प्रॉपर्टी को पहचान के लिए सेट करना होगा और फिर अपना कोड आज़माना होगा।

या फिर आप भी इस का उपयोग कर सकते हैं।

using (var context = new MyContext())
{
  context.MyEntities.AddObject(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Your Identity column ID
}

7
शीर्ष मतदान जवाब के रूप में ही।
लुईस 86

2
StoreGeneratedPatternमेरे लिए लापता टुकड़ा था।
बर्न्सबीए

1
ORACLE और ON-Insert ट्रिगर के साथ काम करने का यही तरीका है,
कार्ल

लिंक टूटा हुआ है - पार्क किया गया डोमेन
t.durden

ओरेकल के साथ हाय मुझे Entity में StoreGeneratedPattern सेट करना था - मॉडल दर्शक पर जाएं, अपनी तालिका और PK ढूंढें, StoreGeneratedPattern संपत्ति का चयन करें और पहचान के लिए सेट करें। यह उक्त उत्तर के रूप में काम करता है। यह उस स्थिति के लिए है जहां आपके पास एक ट्रिगर है जो आपके पीके को एक अनुक्रम से सम्मिलित करता है।
रोब

15

Idडेटाबेस में परिवर्तन को प्रचारित करने के बाद आपके द्वारा सेव की जा रही वस्तु सही होनी चाहिए ।


27
क्या आपने आंतरिक अपवाद देखा है? ;-)
स्नोबैयर

6

आप बचत करने के बाद ही आईडी प्राप्त कर सकते हैं, इसके बजाय आप एक नई गाइडलाइन बना सकते हैं और बचत करने से पहले असाइन कर सकते हैं।


4

मैं एक ऐसी स्थिति में आता हूं जहां मुझे डेटाबेस में डेटा सम्मिलित करने की आवश्यकता होती है और साथ ही साथ इकाई रूपरेखा का उपयोग करके प्राथमिक आईडी की आवश्यकता होती है। समाधान :

long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
 {
    InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
    InfoBase.Add(generalinfo);
    InfoBase.Context.SaveChanges();
    id = entityclassobj.ID;
    return id;
 }

4

सभी उत्तर अपने स्वयं के परिदृश्यों के लिए बहुत अच्छी तरह से अनुकूल हैं, जो मैंने अलग किया वह यह है कि मैंने सीधे पीके को ऑब्जेक्ट (TEntity) से असाइन किया है जो इस तरह से एक इंट चर में वापस जोड़ें ();

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
}

इसलिए एक पूरी नई वस्तु बनाने के बजाय, आप बस वही लें जो आप चाहते हैं :)

EDIT for Mr. @GertArnold:

यहाँ छवि विवरण दर्ज करें


3
यह एक ईद निर्दिष्ट करने के लिए गैर-प्रकटीकरण विधि को जोड़ने के लिए वास्तव में उपयोगी नहीं है। यह भी एंटिटी फ्रेमवर्क से संबंधित नहीं है।
गर्ट अर्नोल्ड

1
@GertArnold .. मैं एक ही सवाल था क्योंकि ओपी मैं जवाब मिला और इसे एक ही पंक्ति में बयान कर दिया, और मैंने समझा करने के लिए गैर-प्रकटीकृत विधि शब्द के बारे में कभी नहीं सुना है ?
IteratioN7T

3
इसका मतलब यह है कि आप जो कुछ भी करते हैं, उसका खुलासा (खुलासा) न करें। शायद यह स्पष्ट रूप से वर्णित नहीं है, मुझे नहीं पता। मुझे पता है कि क्या है Add(यदि यह है DbSet.Add) जादुई रूप से एक मूल्य प्रदान नहीं करता है EmployeeId
गर्ट अर्नोल्ड

3
बिना नहीं SaveChanges। असंभव। जब तक आपके पास कुछ अन्य प्रक्रिया नहीं होती है EmployeeId, उदाहरण के लिए, Employeeनिर्माणकर्ता। या आप EF कोर का उपयोग कर रहे हैं ForSqlServerUseSequenceHiLo। वैसे भी, आप पूरी तस्वीर नहीं दे रहे हैं।
गर्ट अर्नोल्ड

3
मेरी अंतिम टिप्पणी होगी: यह मानक ईएफ व्यवहार नहीं है। आपको अपने पर्यावरण का अधिक विवरण देना चाहिए। ईएफ संस्करण, डेटाबेस ब्रांड और संस्करण, कर्मचारी वर्ग, इसकी मैपिंग विवरण।
गर्ट अर्नोल्ड

3
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;

यह काम करेगा।


4
डेटाबेस में परिवर्तन सहेजने के लिए रिपॉजिटरी जिम्मेदार नहीं है। यह एक UnitOfWork का काम है।
tchelidze

5
इसके अलावा, यह बिल्कुल स्पष्ट नहीं है कि क्या Repositoryहै। और "यह काम करेगा" कुछ स्पष्टीकरण है!
गर्ट अर्नोल्ड

2

दो रणनीतियां हैं:

  1. डेटाबेस-जनरेट ID( intया GUID) का उपयोग करें

    विपक्ष:

    आपको बस बचाई गई संस्थाओं SaveChanges()के IDलिए प्रदर्शन करना चाहिए ।

    पेशेवरों:

    intपहचान का उपयोग कर सकते हैं ।

  2. IDकेवल क्लाइंट का उपयोग करें - GUID।

    पेशेवरों: SaveChangesसंचालन की न्यूनतम । प्रति ऑपरेशन में नई वस्तुओं का एक बड़ा ग्राफ सम्मिलित करने में सक्षम।

    विपक्ष:

    के लिए ही अनुमति दी GUID


1

जब आप पहले EF 6.x कोड का उपयोग करते हैं

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

और एक डेटाबेस तालिका इनिशियलाइज़ करें, यह एक डाल देगा

(newsequentialid())

शीर्ष लेख डिफ़ॉल्ट मान या बाइंडिंग के अंतर्गत तालिका गुणों के अंदर, ID को सम्मिलित करने की अनुमति देता है क्योंकि इसे डाला जाता है।

समस्या यह है कि यदि आप एक तालिका बनाते हैं और जोड़ते हैं

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

बाद में, भविष्य के अपडेट-डेटाबेस वापस नहीं जोड़े जाएंगे (newfterentialid ())

उचित तरीका ठीक करने के लिए माइग्रेशन को मिटा देना है, डेटाबेस को हटाना है और पुनः माइग्रेट करना है ... या आप टेबल डिजाइनर में सिर्फ (newfterentialid ()) जोड़ सकते हैं।


क्या आप इस बारे में विस्तार से बता सकते हैं कि नया परिणाम कहां () जाता है? मेरे पास पहले से ही हाथ से बनाए गए डेटाबेस मॉडल हैं, पहले ईएफ कोड का उपयोग नहीं करते हैं, और यह आईडी नहीं भरता है क्योंकि यह मेरी प्राथमिक कुंजी नहीं है। उसके लिए समाधान खोजना पसंद करेंगे।
जोश

1
@josh कोड को पहले गाइड प्रकार मानकर, Sql Server Management Studio में अपनी तालिका पर राइट क्लिक करें, Id कॉलम पर क्लिक करें, और कॉलम गुण टैब के अंदर, (सामान्य), आपको डिफ़ॉल्ट मान या बाइंडिंग दिखाई देगा। यदि आप हाथ से DB सारणी बना रहे हैं, तो NewSequentialId या NewId देखें । सामान्य उपयोग का मामला कुछ ऐसा हैwhen -column- is NULL, then NEWID()
जेफ ली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.