it-swarm.asia

Entity Framework - استرجع المعرف قبل "SaveChanges" داخل المعاملة

في Entity Framework - هل هناك أي طريقة لاسترداد معرف (هوية) تم إنشاؤه حديثًا داخل معاملة قبل الاتصال بـ "SaveChanges"؟

أحتاج إلى معرف لإدخال ثانٍ ، ومع ذلك يتم إرجاعه دائمًا على أنه 0 ...

        ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;

        objectContext.Connection.Open();

        using (var transaction = objectContext.Connection.BeginTransaction())
        {
            foreach (tblTest entity in saveItems)
            {
                this.context.Entry(entity).State = System.Data.EntityState.Added;
                this.context.Set<tblTest>().Add(entity);

                int testId = entity.TestID;

                .... Add another item using testId
            }

            try
            {
                context.SaveChanges();
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                objectContext.Connection.Close();
                throw ex;
            }
        }

        objectContext.Connection.Close();
53
user1948635

يتم إنشاء المعرف بواسطة قاعدة البيانات بعد إدراج الصف في الجدول. لا يمكنك سؤال قاعدة البيانات عن القيمة التي ستكون قبل إدراج الصف.

لديك طريقتان للتغلب على هذا - الأسهل سيكون الاتصال بـ SaveChanges. نظرًا لأنك داخل معاملة ، يمكنك التراجع في حالة وجود مشكلة بعد الحصول على المعرف.

الطريقة الثانية هي عدم استخدام قاعدة البيانات المضمنة في حقول IDENTITY ، بل تنفيذها بنفسك. يمكن أن يكون هذا مفيدًا للغاية عندما يكون لديك الكثير من عمليات الإدراج المجمّعة ، ولكنه يأتي بسعر - ليس من السهل تطبيقه.

التحرير: يحتوي SQL Server 2012 على نوع SEQUENCE مدمج يمكن استخدامه بدلاً من عمود IDENTITY ، ولا حاجة لتطبيقه بنفسك.

45
zmbq

zmbq صحيح ، يمكنك فقط الحصول على المعرف بعد استدعاء حفظ التغييرات.

اقتراحي هو أنه يجب عليك عدم الاعتماد على المعرف الذي تم إنشاؤه لقاعدة البيانات. يجب أن تحتوي قاعدة البيانات فقط على تفاصيل التطبيق الخاص بك ، وليس جزءًا لا يتجزأ وغير قابل للتغيير.

إذا لم تتمكن من التغلب على هذه المشكلة ، فاستخدم GUID كمعرّف بسبب تفرده. يدعم MSSQL GUID كنوع عمود أصلي وهو سريع (وإن لم يكن أسرع من INT.).

في صحتك

7
SeriousM

إذا كان كيان tblTest الخاص بك متصلاً بالكيانات الأخرى التي تريد إرفاقها ، فلن تحتاج إلى الحصول على المعرف لإنشاء العلاقة. دعنا نقول أن tblTest مرتبط بكائن anotherTest ، إنه بالطريقة التي يوجد بها في كائن anotherTest كائن tblTest وخصائص tblTestId ، في هذه الحالة يمكنك الحصول على هذا الكود:

using (var transaction = objectContext.Connection.BeginTransaction())
    {
        foreach (tblTest entity in saveItems)
        {
            this.context.Entry(entity).State = System.Data.EntityState.Added;
            this.context.Set<tblTest>().Add(entity);

            anotherTest.tblTest = entity;
            ....
        }
    }

بعد تقديم العلاقة سيتم إنشاء ولن تحتاج إلى القلق بشأن المعرفات وغيرها.

4
Armen

كما أشار آخرون بالفعل ، لا يمكنك الوصول إلى قيمة الزيادة التي تم إنشاؤها بواسطة قاعدة البيانات قبل استدعاء saveChanges() - ومع ذلك ، إذا كنت مهتمًا فقط بـ id كوسيلة لإجراء اتصال بكيان آخر (على سبيل المثال في نفس المعاملة ) ثم يمكنك أيضًا الاعتماد على المعرفات المؤقتة المعينة بواسطة EF Core :

اعتمادًا على موفر قاعدة البيانات المستخدمة ، قد يتم إنشاء القيم جانب العميل بواسطة EF أو في قاعدة البيانات. إذا تم إنشاء القيمة بواسطة قاعدة البيانات ، فقد تقوم EF بتعيين قيمة مؤقتة عند إضافة الكيان إلى السياق. ثم سيتم استبدال هذه القيمة المؤقتة بقيمة قاعدة البيانات التي تم إنشاؤها أثناء SaveChanges ().

هنا مثال لشرح كيف يعمل هذا. قل تتم الإشارة إلى MyEntity بواسطة MyOtherEntity عبر الخاصية MyEntityId والتي يجب تعيينها قبل استدعاء saveChanges.

var x = new MyEntity();        // x.Id = 0
dbContext.Add(x);              // x.Id = -2147482624 <-- EF Core generated id
var y = new MyOtherEntity();   // y.Id = 0
dbContext.Add(y);              // y.Id = -2147482623 <-- EF Core generated id
y.MyEntityId = x.Id;           // y.MyEntityId = -2147482624
dbContext.SaveChangesAsync();
Debug.WriteLine(x.Id);         // 1261 <- EF Core replaced temp id with "real" id
Debug.WriteLine(y.MyEntityId); // 1261 <- reference also adjusted by EF Core

يعمل ما سبق أيضًا عند تعيين المراجع عبر الخصائص الملاحية ، أي y.MyEntity = x بدلاً من y.MyEntityId = x.Id

3
B12Toaster

وهناك عمل بسيط حول هذا سيكون

var ParentRecord = new ParentTable () {
SomeProperty = "Some Value",
AnotherProperty = "Another Property Value"
};

ParentRecord.ChildTable.Add(new ChildTable () {
ChildTableProperty = "Some Value",
ChildTableAnotherProperty = "Some Another Value"
});

db.ParentTable.Add(ParentRecord);

db.SaveChanges();

حيث ParentTable و ChildTable هما جدولان متصلان بالمفتاح Foregin.

0
Hamza Khanzada