2009-02-28 12 views
5

मैं प्रोजेक्ट डेटा रिपोजिटरी में ऑब्जेक्ट मैपिंग को समाहित करने का प्रयास कर रहा हूं। शायद ईएफ आवश्यक अवशोषण का स्तर प्रदान करेगा, लेकिन इस कारण से मैं लिंक से एसक्यूएल का उपयोग कर रहा हूं।लिंक से SQL डेटा पहुंच को समाहित करने का सबसे अच्छा तरीका क्या है?

public List<ModUser> GetUsers() { 
    Users.Select(MapUser).ToList(); 
} 

public Expression<Func<User, ModUser>> MapUser { 
    get { 
     return u => new ModUser() { 
      UserId = u.User_Id, 
      UserResources = u.Resources(MapResource) 
     } 
    } 
} 

public Expression<Func<Resource, ModResource>> MapResource { ... 

कोड विफल हो जाएगा के बाद से मैं कर रहा हूँ के रूप में मैं MapResource अभिव्यक्ति फोन नहीं कर सकते हैं: निम्नलिखित कोड ModUser वस्तुओं की एक सूची है, जहां ModUser POCO है कि भंडार को उजागर करता है के रूप में डेटाबेस में उन वापस जाने के लिए करना है इसे एक और अभिव्यक्ति के अंदर से कॉल करने की कोशिश कर रहा है। मैंने u => नए ModResource() के साथ 'MapResource' को प्रतिस्थापित करके, फिर इस प्लेसहोल्डर नोड को ढूंढने और इसे MapResource अभिव्यक्ति के साथ बदलने के लिए ExpressionVisitor का उपयोग करके इसे प्राप्त करने में कामयाब रहा है।

मैं भी इसी तरह के मुद्दों जब मैं केवल एक प्रॉपर्टी है, यानी UserResource = MapResource से जुड़े एक अभिव्यक्ति के साथ ModUser की संपत्ति आवंटित करने के लिए प्रयास करें। अभिव्यक्ति वर्ग पर विधियों का उपयोग करके आवश्यक अभिव्यक्तियों को मैन्युअल रूप से संयोजित करके मैंने इस दूसरे मुद्दे को प्राप्त करने में कामयाब रहा है।

मुझे पता है कि मैं ऊपर कोड को बदल सकता है

UserResources = u.Resources(r => MapResource.Compile().Invoke(r)); 

लेकिन तब करने के लिए अंतिम SQL क्वेरी के बाद से हम कर रहे हैं, आर के सभी गुण, न कि केवल वे MapResouce द्वारा आवश्यक प्राप्त करने के लिए की आवश्यकता होगी उत्पादित अब एक समारोह से निपटने। साथ ही, MapResouce को आर पर आगे की टेबल तक पहुंच की आवश्यकता होनी चाहिए, यह संभव नहीं होगा क्योंकि इसे किसी फ़ंक्शन के रूप में उपयोग नहीं किया जा रहा है। मैं DeferredLoadingEnabled को सत्य पर सेट कर सकता था लेकिन जो भी आवश्यक तालिकाओं के साथ जुड़ने के लिए मुख्य क्वेरी को संशोधित करने के बजाय व्यक्तिगत प्रश्नों की एक बड़ी संख्या को दूर कर देगा।

क्या किसी को पता है, तो इन आपरेशनों नेट के भविष्य के संस्करणों में आसान हो जा रहे हैं या मैं गलत तरीके से इस बारे में जा रहा हूँ है? मुझे वास्तव में लिंक और अभिव्यक्ति की विशेषताएं पसंद हैं, मेरी इच्छा है कि मैं उन्हें अधिक पठनीय कोड का उपयोग करके नियोजित कर सकूं।

अपडेट किया गया

सोचा मैं कैसे मैं भाव अधिक composable बना दिया है के कुछ उदाहरण जोड़ सकते हैं। वे संक्षिप्त नहीं हैं, लेकिन उन्हें नौकरी मिलती है।

public Expression<Func<User, ModUser>> MapUser { 
    get { 
     Expression<Func<User, ModUser>> mapUser = u => new ModUser() { 
      UserId = u.User_Id, 
      UserResources = u.Resources(r => new ModResource()) 
     }; 
     return mapUser.MapResources(this); 
    } 
} 

public Expression<Func<Resource, ModResource>> MapResource { ... } 


public static Expression<Func<T0, T1>> MapResources<T0, T1>(this Expression<Func<T0, T1>> exp, DataContext dc) { 
    return exp.Visit<MethodCallExpression, Expression<Func<T0, T1>>>(m => { 
     if(m.Arguments.Count > 1 && m.Arguments[1].Type == typeof(Func<DataContext.Resource, ModResource>)) { //Find a select statement that has the sub expression as an argument 
      //The resource mapping expression will require the Resource object, which is obtained here 
      ParameterExpression resourceParam = ((LambdaExpression)m.Arguments[1]).Parameters[0]; 
      return Expression.Call(m.Method, m.Arguments[0], //The first argument is the record selection for the 'select' method 
       Expression.Lambda<Func<DataContext.Resource, ModResource>>(//Provide the proper mapping expression as the projection for the 'select' method 
        Expression.Invoke(dc.MapResource, resourceParam), 
        resourceParam) 
       ); 
     } 
     return m; 
    }); 
} 

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

public Expression<Func<User, ModUser>> MapUser { 
    get { 
     Expression<Func<User, ModResource, ModUser>> mapUser = (u, resource) => new ModUser() { 
      UserId = u.User_Id, 
      UserResource = resource; 
     } 

     return mapUser.CollapseArgument(MapResource, user => user.MainResource); 
    } 
} 

public Expression<Func<Resource, ModResource>> MapResource { ... } 

public static Expression<Func<T0, T3>> CollapseArgument<T0, T1, T2, T3>(this Expression<Func<T0, T1, T3>> exp, Expression<Func<T2, T1>> exp0, Expression<Func<T0, T2>> exp1) { 
    var param0 = Expression.Parameter(typeof(T0), "p0"); 
    var argExp = Expression.Invoke(exp0, Expression.Invoke(exp1, param0)); 
    return Expression.Lambda<Func<T0, T3>>(
     Expression.Invoke(exp, param0, argExp), 
     param0); 
} 

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

तो मुझे अभिव्यक्तियों को अत्यधिक संगत बनाने के तरीके मिल गए हैं ...यह सिर्फ साफ महसूस नहीं करता है।

उत्तर

0

मुझे लगता है कि यदि आप पीओसीओ का उपयोग करना चाहते हैं, तो लिंक से एसक्यूएल सबसे अच्छा विकल्प नहीं है। मुझे लगता है कि आप शायद NHibernate जैसे कुछ का उपयोग बंद कर देंगे। पीओसीओ के साथ लिंक से एसक्यूएल का उपयोग करना मतलब है कि आप डेटाबेस के शीर्ष पर डेटा परत (लिंक से एसक्यूएल) के शीर्ष पर एक परत बना रहे हैं। NHibernate के साथ, आप अपना पूरा कोड बनायेंगे और इसे सीधे डेटाबेस में मैप करेंगे। कम परतें == कम कोड == कम काम।

+0

nhibernate @chris उपयोग नहीं किया है, लेकिन यह "कोड" xml फ़ाइलें में मैपिंग के लिए ले जाया नहीं है? – eglasius

+0

फ्लुएंट एनएचबेर्नेट का उपयोग करें - फिर आपको एक्सएमएल के बजाय कोड प्राप्त होता है, जिसमें सभी रिफैक्टरिंग/संकलन समय सत्यापन की अपेक्षा होती है। –

+0

मैं वास्तव में यहां एक लिंक से SQL समाधान की तलाश में हूं क्योंकि एनएचबीर्नेट में जाने के लिए इस प्रोजेक्ट का विकल्प नहीं है। – LaserJesus

1

लिंक से एसक्यूएल पीओसीओ का समर्थन करता है थोड़ा अलग है।

दृढ़ता अज्ञानता प्राप्त करने के लिए, आप एक मैपिंग फ़ाइल का उपयोग करेंगे जो वर्णन करता है कि कैसे एक मॉड्यूसर मैप किया गया है (कॉलम, एसोसिएशन इत्यादि), और एलटीएस डिजाइनर नहीं। जब आप कोई नया संदर्भ बनाते हैं, तो आप इसे XML मैपिंग फ़ाइल को XMLMappingSource के रूप में पास करते हैं।

इस तरह, एलटीएस डेटाबेस से आपकी ऑब्जेक्ट वापस कर देगा।

मैं यहाँ और वहाँ है कि (टी) के प्रकार IList के गुणों पढ़ें/लिखें के रूप में अपने संग्रह संघ गुण को परिभाषित करने के लिए पर्याप्त है LinqToSql उन संग्रहों पर आलसी लोड हो रहा है प्रदान करने के लिए पढ़ा है, लेकिन मैं इसे प्रयास नहीं किया है, इसलिए मैं इसके लिए झुकाव नहीं कर सकते हैं।

एंटिटी फ्रेमवर्क अपने वर्तमान संस्करण में पीओसीओ समर्थन के लिए और भी बदतर होगा (मूल रूप से जहां तक ​​अधिकांश लोग पीओसीओ शब्द को समझते हैं)।

सभी सामान्य एलटीएस सीमाएं इस पर लागू होती हैं, इसलिए कोई "मूल्य वस्तु" मैपिंग नहीं होती है। यदि आप डेटाबेस और पीओसीओ समर्थन से थोड़ी दूर हटाना चाहते हैं, तो आपको NHibernate को देखने की आवश्यकता है।

+0

एक मैपिंग फ़ाइल में मुझे आवश्यक अभिव्यक्ति शक्ति नहीं होगी। ऐसा करने का एकमात्र तरीका यह है कि यह करने योग्य अभिव्यक्तियों की एक श्रृंखला का उपयोग करना है। मेरे पास वास्तव में यह काम है और मैं एक उदाहरण दिखाने के लिए पोस्ट को अपडेट करने जा रहा हूं। यह उतना साफ नहीं है जितना मैं चाहूंगा। – LaserJesus

1

ठीक है मुझे यह मानना ​​है कि मैंने वास्तव में ओपी के प्रश्न (भेड़ का बच्चा) पढ़ना समाप्त नहीं किया था, लेकिन क्या आप जानते थे कि आप किसी भी पीओसीओ ऑब्जेक्ट को सजाने के लिए लिंक-टू-एसक्यूएल विशेषताओं का उपयोग कर सकते हैं? आपको डिजाइनर का उपयोग करने की ज़रूरत नहीं है।

यहां कोड से एक यादृच्छिक उदाहरण है जो अभी मेरे सामने खुला है। यह "उत्पाद" नामक एक पॉको है जिसमें कुछ विशेषताओं को लागू किया गया है जो इसे लिंक-टू-एसक्यूएल डेटाकॉन्टेक्स्ट के साथ बातचीत करने देगा। पिछले कुछ समय से

HTH

using System; 
using System.Collections.Generic; 
using System.Data.Linq; 
using System.Data.Linq.Mapping; 
using System.Linq; 
using System.Web; 

namespace Redacted.Site.Models.Store 
{ 
    /// <summary> 
    /// A "Product" is a good for purchase at the store. 
    /// </summary> 
    [Table(Name = "s.products")] 
    public partial class Product 
    { 
     /// <summary>Gets or sets the PK of the object/row.</summary> 
     [Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL")] 
     public Int32 ID { get; set; } 

     /// <summary>Gets or sets the Title.</summary> 
     [Column(Name = "title", DbType = "NVARCHAR(500) NOT NULL")] 
     public String Title { get; set; } 

     /// <summary>Gets or sets the Lede.</summary> 
     [Column(Name = "lede", DbType = "NVARCHAR(MAX) NOT NULL")] 
     public String Lede { get; set; } 

     /// <summary>Gets or sets the Description.</summary> 
     [Column(Name = "description", DbType = "NTEXT NOT NULL")] 
     public String Description { get; set; } 

     /// <summary>Gets or sets the Price.</summary> 
     [Column(Name = "price", DbType = "FLOAT NOT NULL")] 
     public Double Price { get; set; } 

     /// <summary>Gets or sets the FK to the <see cref="Department"/>.</summary> 
     [Column(Name = "department_id", DbType = "TINYINT NOT NULL")] 
     public Byte DepartmentID { get; set; } 

     /// <summary>Gets or sets the date/time the product was released to the store.</summary> 
     [Column(Name = "released_on_utc", DbType = "DATETIME NOT NULL")] 
     public Int32 ReleasedOnUtc { get; set; } 

    } 
} 
+0

क्या पीओसीओ को पॉप्युलेट करने के लिए इस दृष्टिकोण का उपयोग करना संभव है जो कभी-कभी गैर-तुच्छ संबंधों के माध्यम से कई विशेषताओं से अपने गुण प्राप्त करता है? मेरी प्रारंभिक प्रतिक्रिया यह है कि यह दृष्टिकोण केवल बहुत ही सरल मैपिंग के लिए काम करेगा। क्या आपके पास अधिक जटिल परिदृश्यों के कोई लिंक या उदाहरण हैं? – LaserJesus

+0

निश्चित रूप से। एल 2 एस डिजाइनर सिर्फ एक कोड जनरेटर है। कोई जादू नहीं हैतो आप अपने स्वयं के जेनरेटर के साथ अपने कोड में एल 2 एस डिजाइनर कुछ भी कर सकते हैं। मैं सड़क पर हूं लेकिन अगले हफ्ते अधिक जटिल उदाहरण के साथ इसे संशोधित करूंगा। – Portman

+0

मेरी चिंता यह है कि मैं डिजाइनर के माध्यम से जो कुछ हासिल करना चाहता हूं उसे प्राप्त करने में सक्षम नहीं हूं और मुझे अधिक अभिव्यक्तिपूर्ण साधन मिलना पड़ा है। लेकिन मैं इंतजार करूँगा और एक बार जब वे ऊपर आएंगे तो अधिक जटिल उदाहरण देखेंगे। – LaserJesus

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

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