इकाई फ्रेमवर्क और SQL सर्वर दृश्य


132

कई कारणों से जिनके बारे में मुझे बात करने की स्वतंत्रता नहीं है, हम अपने Sql Server 2005 डेटाबेस पर एक दृश्य को परिभाषित कर रहे हैं जैसे:

CREATE VIEW [dbo].[MeterProvingStatisticsPoint]
AS
SELECT
    CAST(0 AS BIGINT) AS 'RowNumber',
    CAST(0 AS BIGINT) AS 'ProverTicketId',
    CAST(0 AS INT) AS 'ReportNumber',
    GETDATE() AS 'CompletedDateTime',
    CAST(1.1 AS float) AS 'MeterFactor',
    CAST(1.1 AS float) AS 'Density',
    CAST(1.1 AS float) AS 'FlowRate',
    CAST(1.1 AS float) AS 'Average',
    CAST(1.1 AS float) AS 'StandardDeviation',
    CAST(1.1 AS float) AS 'MeanPlus2XStandardDeviation',
    CAST(1.1 AS float) AS 'MeanMinus2XStandardDeviation'
WHERE 0 = 1

विचार यह है कि एंटिटी फ्रेमवर्क इस क्वेरी के आधार पर एक इकाई बनाएगा, जो यह करता है, लेकिन यह इसे एक त्रुटि के साथ उत्पन्न करता है जो निम्नलिखित बताता है:

चेतावनी 6002: तालिका / दृश्य 'Keystone_Local.dbo.MeterProvingStatisticsPoint' में प्राथमिक कुंजी परिभाषित नहीं है। कुंजी का अनुमान लगाया गया है और परिभाषा को केवल-पढ़ने के लिए तालिका / दृश्य के रूप में बनाया गया था।

और यह तय करता है कि कंप्लीटडडेट टाइम फील्ड इस इकाई की प्राथमिक कुंजी होगी।

हम मॉडल उत्पन्न करने के लिए EdmGen का उपयोग कर रहे हैं। क्या एक ऐसा तरीका है जो इकाई ढांचे में प्राथमिक कुंजी के रूप में इस दृश्य के किसी भी क्षेत्र को शामिल नहीं करता है?

जवाबों:


245

हमारे पास एक ही समस्या थी और यह समाधान है:

इकाई कुंजी को एक प्राथमिक कुंजी के रूप में कॉलम का उपयोग करने के लिए बाध्य करने के लिए, ISNULL का उपयोग करें।

इकाई की रूपरेखा को एक प्राथमिक कुंजी के रूप में एक कॉलम का उपयोग नहीं करने के लिए मजबूर करने के लिए, NULLIF का उपयोग करें।

इसे लागू करने का एक आसान तरीका यह है कि आप किसी अन्य चयन में अपने दृश्य का चयन विवरण लपेटें।

उदाहरण:

SELECT
  ISNULL(MyPrimaryID,-999) MyPrimaryID,
  NULLIF(AnotherProperty,'') AnotherProperty
  FROM ( ... ) AS temp

2
मुझे लगता है कि यह सबसे अच्छी उम्मीद है। नीचे की रेखा यह काम करती है।
MvcCmsJon

1
धन्यवाद! इसने पूरी तरह से काम किया। @sabanito मुझे लगता है कि यह परिभाषा को पार्स करता है। यही कारण है कि आपको विशेष रूप से IsNull () में प्रमुख गुणों को लपेटने की आवश्यकता है। मेरे पास एक ऐसा दृष्टिकोण है जो किसी भी नल को वापस नहीं करता है (और किसी भी नल को वापस नहीं कर सकता है) लेकिन जिस तरह से तर्क लिखा गया था, उसके कारण, ईएफ यह निर्धारित नहीं कर सका कि जब तक मैं इसनॉल में चाबियाँ लपेटता नहीं था ()।
रब्बी

3
एकमात्र मुद्दा जो मैं यहां देख रहा हूं वह यह है कि दृश्य को वैध रूप से एक खाली स्ट्रिंग वापस करने की आवश्यकता हो सकती है ''। मैंने जो किया, बस कॉलम को अपने डेटा प्रकार पर वापस कर दिया। उदाहरण के लिए यदि अन्यप्रोपरेटी में varchar (50) का डेटाटाइप था, तो मैं इसे इस तरह के 'CONVERT (VARCHAR (50), एक औरProperty) AS [एक औरProperty] के रूप में डालूंगा। इसने EF से अशक्तता का मुखौटा लगाया और खाली तारों की भी अनुमति दी।
बार्ट

2
हाँ, यह उदाहरण के लिए EF स्तंभ को एक प्राथमिक कुंजी के रूप में उपयोग करने के लिए काम करता है (CONVERT (VARCHAR (50), newid) (), '') AS [PK]
dc2009

2
समाधान में एक कष्टप्रद संदेश होने के अलावा, क्या इसे ठीक नहीं करने में कोई बुराई है? मैं आपके समाधान से सहमत हूं, लेकिन स्पष्ट रूप से मुझे नहीं लगता कि मुझे ऐसा करना चाहिए - मुझे लगता है कि हम सहमत हो सकते हैं कि यह एक बग सही है?
डिस्लेक्सिकनकोको

67

मैं डिजाइनर का उपयोग करके इसे हल करने में सक्षम था।

  1. मॉडल ब्राउज़र खोलें।
  2. चित्र में देखें।
  3. प्राथमिक कुंजी पर राइट क्लिक करें, और सुनिश्चित करें कि "एंटिटी की" की जाँच की गई है।
  4. सभी गैर-प्राथमिक कुंजी का चयन करें। Ctrl या Shift कुंजियों का उपयोग करें।
  5. गुण विंडो में (इसे देखने के लिए यदि आवश्यक हो तो F4 दबाएं), "एंटिटी की" ड्रॉप-डाउन को गलत में बदलें।
  6. परिवर्तनों को सुरक्षित करें।
  7. Visual Studio को बंद करें और इसे फिर से खोलें। मैं EF 6 के साथ विजुअल स्टूडियो 2013 का उपयोग कर रहा हूं और मुझे दूर जाने के लिए चेतावनी प्राप्त करने के लिए ऐसा करना पड़ा।

मुझे ISNULL, NULLIF या COALESCE वर्कअराउंड का उपयोग करने के लिए अपना दृष्टिकोण नहीं बदलना पड़ा। यदि आप डेटाबेस से अपने मॉडल को अपडेट करते हैं, तो चेतावनी फिर से दिखाई देगी, लेकिन यदि आप बंद करते हैं और वीएस को फिर से खोलते हैं तो चले जाएंगे। डिज़ाइनर में आपके द्वारा किए गए परिवर्तन संरक्षित होंगे और ताज़ा से प्रभावित नहीं होंगे।


9
की पुष्टि। चेतावनी को दूर करने के लिए VS2013 को पुनरारंभ करना होगा।
माइकल लोगुटोव

5
"आपने इसे बंद करने या फिर से चलाने की कोशिश की है?" ;-) धन्यवाद, एक आकर्षण की तरह काम करता है!
ओबल टोबेल

4
जब मैं विचार बना रहा होता हूं, तो वे मॉडल आरेख में भी नहीं होते हैं। वे xml फ़ाइल में टिप्पणी कर रहे हैं
ggderas

सरल और आसान समाधान और फ्लो देखने में हेरफेर के रूप में एक nono hacky तय के रूप में ज्यादा लगता है! धन्यवाद।
लुकाजेनसेन

2
पुष्टि VS2017 को दूर जाने की चेतावनी के लिए भी पुनरारंभ करने की आवश्यकता है।
मार्क लेवेस्क

46

@Tillito से सहमत हैं, हालांकि ज्यादातर मामलों में यह एसक्यूएल ऑप्टिमाइज़र को बेकार कर देगा और यह सही इंडेक्स का उपयोग नहीं करेगा।

यह किसी के लिए स्पष्ट हो सकता है, लेकिन मैंने टिलिटो समाधान का उपयोग करते हुए प्रदर्शन के मुद्दों को हल करने के घंटे जला दिए। कहते हैं कि आपके पास तालिका है:

 Create table OrderDetail
    (  
       Id int primary key,
       CustomerId int references Customer(Id),
       Amount decimal default(0)
    );
 Create index ix_customer on OrderDetail(CustomerId);

और आपका नजरिया कुछ इस तरह है

 Create view CustomerView
    As
      Select 
          IsNull(CustomerId, -1) as CustomerId, -- forcing EF to use it as key
          Sum(Amount) as Amount
      From OrderDetail
      Group by CustomerId

Sql ऑप्टिमाइज़र इंडेक्स ix_customer का उपयोग नहीं करेगा और यह प्राथमिक इंडेक्स पर टेबल स्कैन करेगा, लेकिन यदि इसके बजाय:

Group by CustomerId

तुम इस्तेमाल

Group by IsNull(CustomerId, -1)

यह MS SQL (कम से कम 2008) योजना में सही इंडेक्स शामिल करेगा।

अगर


2
यह टिलिटो के उत्तर पर एक टिप्पणी होनी चाहिए, न कि स्वयं एक उत्तर के रूप में, क्योंकि यह ओपी के प्रश्न के लिए एक समाधान प्रदान नहीं करता है।
ज़िम्मदान

6
आदमी के पास 1 का एक प्रतिनिधि है, वह अभी तक एक टिप्पणी नहीं जोड़ सकता है।
jrcs3

@zimdanen कोई तरीका नहीं है कि आप इस जानकारी को एक टिप्पणी में फिट कर सकें, यह एक अलग उत्तर में होने के लिए अधिक समझ में आता है।
कंटैंगो

2
@ कांटांगो: यह जवाब पोस्ट किए जाने के छह दिन बाद संपादित किया गया था और मैंने अपनी टिप्पणी पोस्ट की थी। संशोधन इतिहास देखें।
ज़िम्मदान

9

यह तरीका मेरे लिए अच्छा है। मैं प्राथमिक कुंजी फ़ील्ड के लिए ISNULL () का उपयोग करता हूं, और COALESCE () यदि फ़ील्ड प्राथमिक कुंजी नहीं होनी चाहिए, लेकिन इसमें एक अशक्त मान भी होना चाहिए। यह उदाहरण एक गैर-अशक्त प्राथमिक कुंजी के साथ आईडी फ़ील्ड का उत्पादन करता है। अन्य फ़ील्ड कुंजियाँ नहीं हैं, और उनकी अशक्त विशेषता के रूप में (कोई नहीं) है।

SELECT      
ISNULL(P.ID, - 1) AS ID,  
COALESCE (P.PurchaseAgent, U.[User Nickname]) AS PurchaseAgent,  
COALESCE (P.PurchaseAuthority, 0) AS PurchaseAuthority,  
COALESCE (P.AgencyCode, '') AS AgencyCode,  
COALESCE (P.UserID, U.ID) AS UserID,  
COALESCE (P.AssignPOs, 'false') AS AssignPOs,  
COALESCE (P.AuthString, '') AS AuthString,  
COALESCE (P.AssignVendors, 'false') AS AssignVendors 
FROM Users AS U  
INNER JOIN Users AS AU ON U.Login = AU.UserName  
LEFT OUTER JOIN PurchaseAgents AS P ON U.ID = P.UserID

यदि आपके पास वास्तव में कोई प्राथमिक कुंजी नहीं है, तो आप अपने कोड द्वारा अनदेखा किए गए एक छद्म कुंजी को उत्पन्न करने के लिए ROW_NUMBER का उपयोग करके एक को खराब कर सकते हैं। उदाहरण के लिए:

SELECT
ROW_NUMBER() OVER(ORDER BY A,B) AS Id,
A, B
FROM SOMETABLE

हाँ, मैंने साथ धोखा दिया NEWID() as id, लेकिन यह एक ही विचार है। और वैध उपयोग के मामले हैं - यदि आपको उदाहरण के लिए केवल-पढ़ने का दृश्य मिला है। बदसूरत, ईएफ, बदसूरत।
रफिन

4

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


हम अनुमानित पीके के साथ समान समस्या रखते हैं, इकाई डुप्लिकेट किए गए रिकॉर्ड लौटाती है और पूरी तरह से परेशान होती है। यदि आप Context.Entity.ToList()डुप्लिकेट रिकॉर्ड निष्पादित करते हैं, लेकिन यदि आप सीधे EF द्वारा उत्पन्न SQL क्वेरी (LINQPad के साथ प्राप्त) निष्पादित करते हैं, तो कोई रिकॉर्ड दोहराव नहीं होता है। इकाई ऑब्जेक्ट (POCO) के लिए डेटाबेस रिकॉर्ड मैपिंग में एक समस्या होने लगती है, क्योंकि पीके व्याख्या किए गए तर्क (गैर अशक्त स्तंभ) का उपयोग करके अनुमान लगाया जाता है।
डेविड ओलिवान उबिएटो

3

ऐसा लगता है कि यह EdmGen के साथ एक ज्ञात समस्या है: http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/12aaac4d-2be8-44f3-9448-d7c659585945/


यह समझ आता है। तो, क्या एक स्तंभ को परिभाषित करने का एक तरीका है क्योंकि हम इसे परिभाषित कर रहे हैं जिस तरह से एक दृश्य में शून्य या अशक्त नहीं है?
सर्जियो रोमेरो

1
क्षमा करें, मैं पहले से ही एंटिटी फ्रेमवर्क में अपनी विशेषज्ञता के स्तर से परे हूं। :-)
RBarryYoung

1
कोई भी जानता है कि यह मुद्दा कब तय होने वाला है? जब आप गैर नल स्तंभ हैं जो प्राथमिक कुंजियाँ नहीं हैं, तो इसे हल करने के लिए कष्टप्रद है।
लाइव-लव

3

एक दृश्य प्राप्त करने के लिए मुझे केवल एक प्राथमिक कुंजी कॉलम दिखाना था मैंने एक दूसरा दृश्य बनाया जो पहले बताया और प्रकारों को अशक्त बनाने के लिए NULLIF का उपयोग किया। यह मेरे लिए ईएफ को लगता है कि दृश्य में सिर्फ एक प्राथमिक कुंजी थी बनाने के लिए काम किया।

यकीन नहीं है कि अगर यह आपकी मदद करेगा क्योंकि मुझे विश्वास नहीं है कि ईएफ कोई प्राथमिक कुंजी के साथ एक इकाई को स्वीकार नहीं करेगा।


3

यदि आप प्राथमिक कुंजी क्या होना चाहिए के साथ गड़बड़ नहीं करना चाहते हैं, तो मैं सुझाव देता हूं:

  1. ROW_NUMBERअपने चयन में शामिल करें
  2. इसे प्राथमिक कुंजी के रूप में सेट करें
  3. मॉडल में गैर-प्राथमिक के रूप में अन्य सभी कॉलम / सदस्य सेट करें

1

उपर्युक्त समस्याओं के कारण, मैं तालिका मूल्य कार्यों को प्राथमिकता देता हूं।

यदि आपके पास यह है:

CREATE VIEW [dbo].[MyView] AS SELECT A, B FROM dbo.Something

इसे बनाएं:

CREATE FUNCTION MyFunction() RETURNS TABLE AS RETURN (SELECT * FROM [dbo].[MyView])

तब आप केवल दृश्य के बजाय फ़ंक्शन आयात करते हैं।


2
आप इस दृष्टिकोण के साथ जाने वाली संस्थाओं के बीच कैसे संबंध बनाएंगे? क्या यह संभव है?
ggderas
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.