पहली क्वेरी के बिना रिकॉर्ड अपडेट करें?


103

आइए हम डेटाबेस को क्वेरी करते हैं और मदों की एक सूची लोड करते हैं। फिर मैं एक आइटम को डिटेल व्यू फॉर्म में खोलता हूं, और डेटाबेस से आइटम को फिर से क्वेरी करने के बजाय, मैं सूची में डेटा स्रोत से आइटम का एक उदाहरण बनाता हूं।

क्या कोई ऐसा तरीका है जो मैं व्यक्तिगत आइटम के रिकॉर्ड को प्राप्त किए बिना डेटाबेस रिकॉर्ड को अपडेट कर सकता हूं?

यहाँ एक नमूना है कि मैं इसे अभी कैसे कर रहा हूँ:

dataItem itemToUpdate = (from t in dataEntity.items
                                 where t.id == id
                                 select t).FirstOrDefault();

फिर रिकॉर्ड खींचने के बाद मैं आइटम में कुछ मान अपडेट करता हूं और रिकॉर्ड को पीछे धकेलता हूं:

itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();

मुझे लगता है कि ऐसा करने का एक बेहतर तरीका होगा, कोई विचार?


2
यह बहुत बुरा तरीका नहीं है ओ चीजें करते हैं। क्या आपके पास उस तालिका तक समवर्ती पहुँच है?
हेनक होल्टरमैन

मुझे लगता है कि यह उपयोग है कि EF की तरह एक ORM सेवा करने के लिए बिल्कुल है। अंतर्निहित DB कार्यान्वयन के लिए चिंता किए बिना, आप जिन वस्तुओं को बनाना / संशोधित / हटाना चाहते हैं, उन पर किए जाने वाले आवेदन के संदर्भ में संचालन की अनुमति देना?
पेरो पी।

40
मुझे लगता है कि टीएसक्यूएल में पृष्ठभूमि वाले डेवलपर्स के लिए ओआरएम को स्वीकार करने और गले लगाने की कोशिश की जा रही है, यह केवल इसे अपडेट करने के लिए रिकॉर्ड देखने के लिए थोड़ा अक्षम है, और कभी भी डेटा का उपयोग नहीं करता है। यह अवधारणा कि किसी डेवलपर को अंतर्निहित DB कार्यान्वयन से संबंधित होने की आवश्यकता नहीं है, एक क्रॉक है। एक डेवलपर जितना अधिक पूरे सिस्टम के बारे में जानता है, उतना ही बेहतर समाधान हो सकता है। विकल्प कभी भी बुरी चीज नहीं होते हैं।
बैरीपिकर

1
ORM दृष्टिकोण वास्तविक वस्तुओं के लिए ठीक है, लेकिन यदि आप अपने डेटाबेस में अन्य चीजों को भी स्टोर करते हैं (जैसे कि बड़े बाइनरी ब्लब्स) तो यह सुपर उपयोगी हो सकता है कि पहले मूल सामग्री को लोड किए बिना उन्हें अपडेट करने में सक्षम हो।
BrainSlugs83

जवाबों:


68

आपको अटैच () विधि का उपयोग करना चाहिए ।

कोचिंग और वस्तुओं का पता लगाना


16
क्या आप एक उदाहरण प्रदान कर सकते हैं?
बार्ट कैलिक्सो

16
context.Products.Attach (उत्पाद); संदर्भ.इंट्री (उत्पाद)।
गेब्रियल

6
@ गैब्रिएल हालांकि सभी संपत्तियों को अपडेट नहीं करेगा? क्या होगा यदि मैं केवल एक को संशोधित करना चाहता हूं?
डेविड फेफर

22
हां यह सभी संपत्तियों को अपडेट कर देगा। यदि आप किसी एकल संपत्ति को अपडेट करना चाहते हैं, तो आप ऐसा कर सकते हैं: संदर्भ। सूचना (उपयोगकर्ता) .Property (x => x.Property) .IsModified = true; (यहाँ एक नज़र है stackoverflow.com/a/5567616/57369 )
गेब्रियल

6
मैं केवल उस संदर्भ को जोड़ना चाहूंगा। एंट्री () केवल .net 4.1 में उपलब्ध है, यदि आप अभी भी 4.0 (मेरे जैसे) का उपयोग कर रहे हैं तो वैकल्पिक के लिए इसे देखें: stackoverflow.com/questions/7113434/where-is- संदर्भ-प्रविष्टि जो अनिवार्य रूप से है: संदर्भ। BjectStateManager.ChangeObjectState (yourObject, EntityState.Modified);
डिस्लेक्सिकानबोको

39

आप डेटाबेस के विरुद्ध डेटास्टोर के संदर्भ में प्रत्यक्ष SQL का उपयोग कर सकते हैं। उदाहरण:

dataEntity.ExecuteStoreCommand
   ("UPDATE items SET itemstatus = 'some status' WHERE id = 123 ");

प्रदर्शन कारणों से, आप एक एकल कोडित SQL स्ट्रिंग के बजाय चर में पारित करना चाह सकते हैं। यह SQL सर्वर क्वेरी को कैश करने और मापदंडों के साथ पुन: उपयोग करने की अनुमति देगा। उदाहरण:

dataEntity.ExecuteStoreCommand
   ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });

अद्यतन - EF 6.0 के लिए

dataEntity.Database.ExecuteSqlCommand
       ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });

9
आप बिना टिप्पणी छोड़े इस उत्तर को क्यों छोड़ देंगे। यह सुझाव मूल लेखकों को स्पॉट-ऑन पर संबोधित करता है।
बैरीपिकर

18
ExecuteStoreCommandवास्तव में ऐसा करने का ईएफ तरीका नहीं है, यह सिर्फ कमांड को निष्पादित करने के लिए DbConnectionअंदर निहित का उपयोग कर रहा है DbContext। यह डेटाबेस अज्ञेयवादी नहीं है, अकेले दृढ़ता अज्ञेय को रहने दें (जैसे कि यह उदाहरण दुर्घटनाग्रस्त हो जाएगा यदि ओपी एक्सएमएल में बदल जाए)।
just.another.programmer

9
@ just.another.programmer - बड़ी शक्ति के साथ बड़ी जिम्मेदारी आती है।
बैरीपिकर

13
क्या यह दृढ़ता अज्ञेय होना है? ऐसा नहीं है कि आप हर दूसरे दिन अपने स्टोरेज सिस्टम को बदलने वाले हैं।
डेविड

5
@ BrainSlugs83 - लिंक सर्वर पर EF का उपयोग करने का प्रयास करें जो केवल OpenQuery का समर्थन करता है - बहुत मज़ा। कभी-कभी आपको काम पाने के लिए कच्चे SQL की आवश्यकता होती है। हमेशा आप परीक्षण के लिए कोड को अलगाव में नहीं खींच सकते। यह एक आदर्श दुनिया नहीं है।
बैरीपिकर

20

कोड:

ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 });
exampleEntity.ExampleProperty = "abc";
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();

परिणाम TSQL:

exec sp_executesql N'UPDATE [dbo].[ExampleEntities]
SET [ExampleProperty ] = @0
WHERE ([Id] = @1)
',N'@0 nvarchar(32),@1 bigint',@0='abc',@1=1

ध्यान दें:

"IsModified = true" लाइन की आवश्यकता है, क्योंकि जब आप नई ExampleEntity ऑब्जेक्ट बनाते हैं (केवल Id प्रॉपर्टी के साथ) तो अन्य सभी प्रॉपर्टीज में उनके डिफ़ॉल्ट मान (0, null, आदि) होते हैं। यदि आप DB को "डिफ़ॉल्ट मान" के साथ अद्यतन करना चाहते हैं, तो परिवर्तन का पता इकाई ढाँचे द्वारा नहीं लगाया जाएगा, और फिर DB अद्यतन नहीं किया जाएगा।

उदाहरण में:

exampleEntity.ExampleProperty = null;

"IsModified = true" लाइन के बिना काम नहीं करेगा, क्योंकि उदाहरण ExampleProperty, पहले से ही शून्य है जब आपने खाली ExampleEntity ऑब्जेक्ट बनाया था, तो आपको EF से यह कहने की आवश्यकता है कि यह कॉलम अपडेट होना चाहिए, और यह इस लाइन का उद्देश्य है।


यह पूर्ण है। मैंने बस इसका परीक्षण किया और यह वही है जो मैं चाहता था। मैं चाहता हूं कि परिवर्तन EF बुनियादी ढांचे (EntityFramework.Triggers परियोजना का उपयोग करके) के माध्यम से जाना चाहिए, लेकिन केवल प्राथमिक कुंजी होने के साथ 1 कॉलम को बदलने में सक्षम होना चाहता था।
माइकजैनन

11

यदि DataItemफ़ील्ड में EF पूर्व-मान्य होगा (जैसे कि अशक्त क्षेत्र), तो हमें इसके लिए उस सत्यापन को अक्षम करना होगा:

DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus };
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.Configuration.ValidateOnSaveEnabled = false;
dataEntity.SaveChanges();
//dataEntity.Configuration.ValidateOnSaveEnabled = true;

अन्यथा हम पूर्व-सत्यापन को संतुष्ट करने का प्रयास कर सकते हैं और फिर भी केवल एकल कॉलम को अपडेट कर सकते हैं:

DataItem itemToUpdate = new DataItem
{
    Id = id,
    Itemstatus = newStatus,
    NonNullableColumn = "this value is disregarded - the db original will remain"
};
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.SaveChanges();

यह मानते हुए dataEntity लेना एक हैSystem.Data.Entity.DbContext

आप इसे इसमें जोड़कर उत्पन्न क्वेरी को सत्यापित कर सकते हैं DbContext:

/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m);

2

माइक्रोसॉफ्ट के गेटिंग स्टार्टेड के हिस्से के रूप में यह लेख बताता है कि यह कैसे करना है:

जोड़ें / संलग्न करें और एंटिटी स्टेट्स

अनुभाग देखें 'एक मौजूदा लेकिन संशोधित इकाई को संदर्भ में संलग्न करना'

अब मैं इन ट्यूटोरियल के बाकी हिस्सों को पढ़ने के लिए तैयार हूँ।


0

यह EF कोर में कुछ अलग काम करता है:

EF Core में ऐसा करने का एक तेज़ तरीका हो सकता है, लेकिन निम्नलिखित का चयन किए बिना एक अद्यतन सुनिश्चित करता है (EF Core 2 और JET के साथ .NET फ्रेमवर्क 4.6.2 पर परीक्षण किया गया):

सुनिश्चित करें कि आपके मॉडल में IsRequired गुण नहीं हैं

फिर निम्नलिखित टेम्पलेट का उपयोग करें (VB.NET में):

    Using dbContext = new MyContext()
        Dim bewegung = dbContext.MyTable.Attach(New MyTable())
        bewegung.Entity.myKey = someKey
        bewegung.Entity.myOtherField = "1"

        dbContext.Entry(bewegung.Entity).State = EntityState.Modified
        dbContext.Update(bewegung.Entity)

        Dim BewegungenDescription = (From tp In dbContext.Model.GetEntityTypes() Where tp.ClrType.Name = "MyTable" Select tp).First()
        For Each p In (From prop In BewegungenDescription.GetProperties() Select prop)
            Dim pp = dbContext.Entry(bewegung.Entity).Property(p.Name)
            pp.IsModified = False
        Next
        dbContext.Entry(bewegung.Entity).Property(Function(row) row.myOtherField).IsModified = True
        dbContext.SaveChanges()
    End Using

-1

सामान्यतया, यदि आपने सभी वस्तुओं को क्वेरी करने के लिए एंटिटी फ्रेमवर्क का उपयोग किया है, और आपने इकाई ऑब्जेक्ट को सहेजा है, तो आप निकाय ऑब्जेक्ट में अलग-अलग आइटम को अपडेट कर सकते हैं और SaveChanges()समाप्त होने पर कॉल कर सकते हैं। उदाहरण के लिए:

var items = dataEntity.Include("items").items;
// For each one you want to change:
items.First(item => item.id == theIdYouWant).itemstatus = newStatus;
// After all changes:
dataEntity.SaveChanges();

आपके द्वारा इच्छित एक आइटम की पुनर्प्राप्ति एक नई क्वेरी उत्पन्न नहीं होनी चाहिए।


दिलचस्प जवाब, क्या किसी और ने भी इसकी पुष्टि की है?
इयान

5
यह ओपी की समस्या के समान काम करता है: पूरे रिकॉर्ड को प्राप्त करें, फिर इसे अपडेट करें। .First () ऑब्जेक्ट को डिसेर्बलाइज करता है।
जेरथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.