2009-08-08 19 views
5

का उपयोग करके प्राथमिक कुंजी निर्धारित करें मैं एक LINQ से SQL आधारित भंडार लिख रहा हूं जहां मैं एक int पैरामीटर के साथ GetByID को अनुमति देना चाहता हूं। हस्ताक्षर है:LINQ से SQL

public T GetByID(int id) 
{ 
    // Return 
    return _dataContext.GetTable<T>() ....; 
} 

मेरी तालिकाओं में प्राथमिक कुंजी के लिए अलग-अलग नाम हैं। मैं जो करना चाहता हूं वह प्रत्येक टी के लिए गतिशील रूप से निर्धारित करता है जो प्राथमिक कुंजी है और इसे पूर्णांक = आईडी के मान के लिए पूछताछ करता है। कोई विचार यह कैसे सबसे अच्छा खींचने के लिए?

+0

क्षमा करें, मेरा उत्तर अच्छा नहीं था - मैं एक 'टेबल ', जो डेटाबेस प्रश्नों के साथ वस्तुओं का इन-स्मृति सूची उलझन में। इस प्रश्न का पहले यहां उत्तर दिया गया था: http://stackoverflow.com/questions/735140/c-linq-to-sql-refectoring-this-generic-getbyid-method –

उत्तर

3

Dennis Troller answered यह सवाल है कि बेन ने प्रश्न में टिप्पणियों में लिंक किया था।

3

व्यक्तिगत रूप से, मुझे लगता है कि यह आसान हो एक SingleOrDefault<T> विधि है कि एक Func<int,T> चयनकर्ता तर्क लेता प्रदान करने के लिए होगा। फिर आप जो भी चयनकर्ता चाहते हैं उसे प्रदान कर सकते हैं, जिसमें उस तालिका की आईडी के आधार पर चयन किया गया है।

public abstract class Repository<T> where T : class 
{ 
    public abstract T GetById(int id); 
    public T SingleOrDefault(Func<int,T> selector) 
    { 
      return _dataContext.GetTable<T>().SingleOrDefault(selector); 
    } 
} 

उपयोग:

var myObj = repos.SingleOrDefault<MyClass>(c => c.MyClassID == id); 

एक जोरदार टाइप respository तो GetById लागू करने के लिए()

public class MyClassRepository : Repository<MyClass> 
{ 
    public override MyClass GetById(int id) 
    { 
     return this.SingleOrDefault(c => c.MyClassID == id); 
    } 
} 
+0

क्या आप वास्तव में पारित आईडी को चेक करना नहीं भूल गए 'सी। MyClassID' के खिलाफ मूल्य? – GregL

+0

@ ग्रेगेल - अच्छी पकड़। फिक्स्ड। – tvanfosson

10

कुछ नीचे की तरह (जो सिर्फ int के अलावा अन्य प्रकार का समर्थन करता इस विधि का उपयोग कर सकता है, लेकिन int पर डिफ़ॉल्ट)। महत्वपूर्ण बात यह है कि प्रतिबिंब के माध्यम से Attribute डेटा देखने के जाल में मत आना; LINQ करने वाली एसक्यूएल भी गुण के बिना वस्तुओं का समर्थन करता है:

public static TEntity Get<TEntity>(this DataContext dataContext, int id) 
     where TEntity : class 
{ 
    return Get<TEntity, int>(dataContext, id); 
} 
public static TEntity Get<TEntity, TKey>(this DataContext dataContext, TKey id) 
    where TEntity : class 
{ 
    // get the row from the database using the meta-model 
    MetaType meta = dataContext.Mapping.GetTable(typeof(TEntity)).RowType; 
    if (meta.IdentityMembers.Count != 1) throw new InvalidOperationException(
     "Composite identity not supported"); 
    string idName = meta.IdentityMembers[0].Member.Name; 

    var param = Expression.Parameter(typeof(TEntity), "row"); 
    var lambda = Expression.Lambda<Func<TEntity, bool>>(
     Expression.Equal(
      Expression.PropertyOrField(param, idName), 
      Expression.Constant(id, typeof(TKey))), param); 

    return dataContext.GetTable<TEntity>().Single(lambda); 
} 
+0

यह निश्चित रूप से सबसे अच्छा तरीका है, और इसके अलावा एक अच्छा जवाब है, क्योंकि यह LINQ से SQL के कम ज्ञात फीचर (रनटाइम मेटाडेटा) को इंगित करता है। –