2011-09-19 14 views
75

में मल्टीमैपिंग का सही उपयोग मैं उत्पाद Items और संबंधित ग्राहकों की एक सूची वापस करने के लिए डैपर की मल्टीमैपिंग सुविधा का उपयोग करने का प्रयास कर रहा हूं।डैपर

[Table("Product")] 
public class ProductItem 
{ 
    public decimal ProductID { get; set; }   
    public string ProductName { get; set; } 
    public string AccountOpened { get; set; } 
    public Customer Customer { get; set; } 
} 

public class Customer 
{ 
    public decimal CustomerId { get; set; } 
    public string CustomerName { get; set; } 
} 

मेरे व्यवसायिक कोड के रूप में

var sql = @"select * from Product p 
      inner join Customer c on p.CustomerId = c.CustomerId 
      order by p.ProductName"; 

var data = con.Query<ProductItem, Customer, ProductItem>(
    sql, 
    (productItem, customer) => { 
     productItem.Customer = customer; 
     return productItem; 
    }, 
    splitOn: "CustomerId,CustomerName" 
); 

यह ठीक काम करता है इस प्रकार है, लेकिन मैं splitOn पैरामीटर के लिए पूरा स्तंभ सूची में जोड़ने के लिए सभी ग्राहकों के गुण वापस जाने के लिए है लगता है है। अगर मैं "ग्राहक नाम" नहीं जोड़ता हूं तो यह शून्य हो जाता है। क्या मैं मल्टीमैपिंग सुविधा की मूल कार्यक्षमता को याद करता हूं। मैं हर बार कॉलम नामों की पूरी सूची जोड़ना नहीं चाहता हूं।

var sql = "select cast(1 as decimal) ProductId, 'a' ProductName, 'x' AccountOpened, cast(1 as decimal) CustomerId, 'name' CustomerName"; 

var item = connection.Query<ProductItem, Customer, ProductItem>(sql, 
    (p, c) => { p.Customer = c; return p; }, splitOn: "CustomerId").First(); 

item.Customer.CustomerId.IsEqualTo(1); 

splitOn परम ईद के लिए, विभाजन बिंदु के रूप में निर्दिष्ट करने की आवश्यकता है यह चूक:

+0

वास्तव में डेटाग्रिडव्यू में दोनों टेबलों को वास्तव में कैसे दिखाएं? एक छोटा सा उदाहरण बहुत सराहना की जाएगी। –

उत्तर

124

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

अपने recordset इस तरह दिखता है कहते हैं:

 
ProductID | ProductName | AccountOpened | CustomerId | CustomerName 
--------------------------------------- ------------------------- 

डैप्पर पता है कि कैसे 2 वस्तुओं में इस क्रम में स्तंभों को विभाजित करने की जरूरत है। एक कर्सर दिखता है कि ग्राहक कॉलम CustomerId पर शुरू होता है, इसलिए splitOn: CustomerId

एक बड़ा यहाँ चेतावनी है, अगर अंतर्निहित तालिका में कॉलम आदेश किसी कारण से फ़्लिप किया जाता है:

 
ProductID | ProductName | AccountOpened | CustomerName | CustomerId 
--------------------------------------- ------------------------- 

splitOn: CustomerId एक अशक्त ग्राहक का नाम का परिणाम देगा।

यदि आप CustomerId,CustomerName को विभाजित बिंदु के रूप में निर्दिष्ट करते हैं, तो डैपर मानते हैं कि आप परिणाम सेट को 3 ऑब्जेक्ट्स में विभाजित करने की कोशिश कर रहे हैं। सबसे पहले शुरुआत में शुरू होता है, दूसरा CustomerId पर शुरू होता है, तीसरा CustomerName पर।

+0

धन्यवाद सैम। हाँ आपका अधिकार यह कॉलम का रिटर्न ऑर्डर था जो ग्राहक नाम के साथ मुद्दा था ग्राहक आईडी वापस लौटाया गया ग्राहक नाम वापस आ रहा था। –

+6

याद रखने की एक बात यह है कि आपके पास 'स्प्लिटन', यानी 'ग्राहक आईडी, ग्राहक नाम 'में' ग्राहक आईडी, ग्राहक नाम 'नहीं है, क्योंकि डैपर स्ट्रिंग स्प्लिट के परिणामों को' ट्रिम 'नहीं करता है। यह सिर्फ जेनेरिक स्प्लिटन त्रुटि फेंक देगा। मुझे एक दिन पागल कर दिया। – jes

+0

क्या होगा अगर मैं ग्राहकों के खिलाफ उत्पादों की सूची प्राप्त करना चाहता हूं? Dapper.Net में इस परिदृश्य को कैसे संभालेंगे? – touseefkhan4pk

2

एक और चेतावनी है। यदि ग्राहक आईडी फ़ील्ड शून्य है (आमतौर पर बाएं जुड़ने वाले प्रश्नों में) डैपर उत्पादइटम को ग्राहक = शून्य के साथ बनाता है। उपर्युक्त उदाहरण में:

var sql = "select cast(1 as decimal) ProductId, 'a' ProductName, 'x' AccountOpened, cast(null as decimal) CustomerId, 'n' CustomerName"; 
var item = connection.Query<ProductItem, Customer, ProductItem>(sql, (p, c) => { p.Customer = c; return p; }, splitOn: "CustomerId").First(); 
Debug.Assert(item.Customer == null); 

और यहां तक ​​कि एक और चेतावनी/जाल। यदि आप splitOn में निर्दिष्ट फ़ील्ड को मैप नहीं करते हैं और उस फ़ील्ड में नल डैपर बनाता है और संबंधित ऑब्जेक्ट (इस मामले में ग्राहक) भरता है। पिछले वर्ग के साथ इस वर्ग का उपयोग प्रदर्शित करने के लिए:

public class Customer 
{ 
    //public decimal CustomerId { get; set; } 
    public string CustomerName { get; set; } 
} 
... 
Debug.Assert(item.Customer != null); 
Debug.Assert(item.Customer.CustomerName == "n"); 
+0

ग्राहक के वर्ग में जोड़ने के अलावा दूसरे उदाहरण का समाधान है? मुझे कोई समस्या है जहां मुझे एक शून्य वस्तु की आवश्यकता है, लेकिन यह मुझे एक खाली वस्तु दे रहा है। (http://stackoverflow.com/questions/27231637/dapper-left-joins-not-returning-null-object-but-an-empty-object) –

0

मैं इसे सामान्य रूप से अपने रेपो में करता हूं, मेरे उपयोग के मामले के लिए अच्छा काम करता है। मैंने सोचा कि मैं साझा करूंगा। शायद कोई इसे आगे बढ़ाएगा।

कुछ कमियां हैं:

  • यह मानती है कि आपके विदेशी कुंजी गुण अपने बच्चे ऑब्जेक्ट का नाम + "आईडी", उदा हैं UnitId।
  • मेरे पास यह केवल माता-पिता को 1 बाल वस्तु का मानचित्रण कर रहा है।

कोड:

public IEnumerable<TParent> GetParentChild<TParent, TChild>() 
    { 
     var sql = string.Format(@"select * from {0} p 
     inner join {1} c on p.{1}Id = c.Id", 
     typeof(TParent).Name, typeof(TChild).Name); 

     Debug.WriteLine(sql); 

     var data = _con.Query<TParent, TChild, TParent>(
      sql, 
      (p, c) => 
      { 
       p.GetType().GetProperty(typeof (TChild).Name).SetValue(p, c); 
       return p; 
      }, 
      splitOn: typeof(TChild).Name + "Id"); 

     return data; 
    } 
6

हमारी टेबल, उसी प्रकार तुम्हारा करने के लिए नामित कर रहे हैं, जहां की तरह "CustomerID" दो बार से '* चुनें' आपरेशन का उपयोग कर वापस आ रहा हो सकता है कुछ। इसलिए, साफ-सुथरी अपना काम कर रही है लेकिन अभी बहुत जल्दी (संभवतः) बंटवारे, क्योंकि कॉलम होगा:

(select * might return): 
ProductID, 
ProductName, 
CustomerID, --first CustomerID 
AccountOpened, 
CustomerID, --second CustomerID, 
CustomerName. 

यह spliton बनाता है: पैरामीटर इतना उपयोगी नहीं है, खासकर जब आप वाकई क्या कॉलम आदेश नहीं कर रहे हैं वापस आ गए हैं। बेशक आप मैन्युअल रूप से कॉलम निर्दिष्ट कर सकते हैं ... लेकिन यह 2017 है और हम शायद ही कभी मूल वस्तु के लिए ऐसा करते हैं।

हम क्या करते हैं, और यह कई सालों से हजारों प्रश्नों के लिए बहुत अच्छा काम करता है, बस आईडी के लिए उपनाम का उपयोग करता है, और कभी भी स्प्लिटन निर्दिष्ट नहीं करता है (डैपर के डिफ़ॉल्ट 'आईडी' का उपयोग करके)।

select 
p.*, 

c.CustomerID AS Id, 
c.* 

... voila! डैपर केवल आईडी पर डिफ़ॉल्ट रूप से विभाजित होगा, और वह आईडी सभी ग्राहक कॉलम से पहले होती है। निस्संदेह यह आपके रिटर्न परिणाम में एक अतिरिक्त कॉलम जोड़ देगा, लेकिन यह जानने के लिए कि कौन से कॉलम से संबंधित हैं, यह जानने के लिए उपयोग की गई अतिरिक्त उपयोगिता के लिए यह बेहद कम ओवरहेड है। और आप आसानी से इसका विस्तार कर सकते हैं। पता और देश की जानकारी चाहिए?

select 
p.*, 

c.CustomerID AS Id, 
c.*, 

address.AddressID AS Id, 
address.*, 

country.CountryID AS Id, 
country.* 

और सबसे अच्छी बात आप स्पष्ट रूप से जो स्तंभ जो वस्तु के साथ जुड़े रहे एसक्यूएल का एक minial राशि में दिखा रहे हैं। डैपर बाकी करता है।

+1

यह सुंदर है। धन्यवाद! –

संबंधित मुद्दे