2010-06-02 17 views
11

मैं ऑब्जेक्ट की प्राथमिक कुंजी खोजने के लिए ईएफ 4 का उपयोग करके एक सामान्य विधि बनाने की कोशिश कर रहा हूं।इकाई फ्रेमवर्क 4: प्राथमिक कुंजी कैसे खोजें?

उदाहरण

public string GetPrimaryKey<T>() 
{ 
    ... 
} 

अधिक जानकारी मैं Tekpub StarterKit के बंद काम कर रहा हूँ और नीचे वर्ग मैं प्राप्त करने की कोशिश कर रहा हूँ और

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Data.Objects; 
using System.Data.Objects.ELinq; 
using System.Data.Linq; 
using Web.Infrastructure.Storage.EF4; 

namespace Web.Infrastructure.Storage { 
public class EFSession:ISession { 
    PuzzleEntities _db;//This is an ObjectContext 
    public EFSession() { 
     _db = new PuzzleEntities(); 
    } 

    public void CommitChanges() { 
     _db.SaveChanges(); 
    } 
    /// <summary> 
    /// Gets the table provided by the type T and returns for querying 
    /// </summary> 
    private ObjectSet<T> GetObjectSet<T>() where T:class { 
     return _db.CreateObjectSet<T>(); 
    } 

    private T GetByPrimaryKey<T>() where T: class 
    { 
     ..... 
    } 

    public void Delete<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T: class{ 

     foreach (T item in All<T>().Where(expression)) 
     { 
      GetObjectSet<T>().DeleteObject(item); 
     } 
    } 

    public void Delete<T>(T item) where T : class { 
     GetObjectSet<T>().DeleteObject(item); 
    } 

    public void DeleteAll<T>() where T : class { 
     foreach(T item in All<T>()) 
     { 
      GetObjectSet<T>().DeleteObject(item); 
     } 
    } 

    public void Dispose() { 
     _db.Dispose(); 
    } 

    public T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T:class { 
     return GetObjectSet<T>().SingleOrDefault(expression); 
    } 

    public IQueryable<T> All<T>() where T : class { 
     return GetObjectSet<T>().AsQueryable(); 
    } 

    public void Add<T>(T item) where T : class { 
     GetObjectSet<T>().AddObject(item); 
    } 
    public void Add<T>(IEnumerable<T> items) where T : class { 
     foreach (T item in items) 
     { 
      GetObjectSet<T>().AddObject(item); 
     } 
    } 
    public void Update<T>(T item) where T : class { 
     //nothing needed here 
    } 
} 
} 

उत्तर

15

तो आखिरकार मैं यह पता लगाने में सक्षम था कि इसे कैसे काम पर लाया जाए। काश मैं कल रात पढ़ने वाले ब्लॉग के लिंक को खो नहीं गया था क्योंकि मैंने कोड नहीं लिखा था।

public T GetByPrimaryKey<T>(int id) where T : class 
{ 
    return (T)_db.GetObjectByKey(new EntityKey(_db.DefaultContainerName + "." + this.GetEntityName<T>(), GetPrimaryKeyInfo<T>().Name, id)); 
} 

string GetEntityName<T>() 
{ 
    string name = typeof(T).Name; 
    if (name.ToLower() == "person") 
     return "People"; 
    else if (name.Substring(name.Length - 1, 1).ToLower() == "y") 
     return name.Remove(name.Length - 1, 1) + "ies"; 
    else if (name.Substring(name.Length - 1, 1).ToLower() == "s") 
     return name + "es"; 
    else 
     return name + "s"; 
} 

private PropertyInfo GetPrimaryKeyInfo<T>() 
{ 
    PropertyInfo[] properties = typeof(T).GetProperties(); 
    foreach (PropertyInfo pI in properties) 
    { 
     System.Object[] attributes = pI.GetCustomAttributes(true); 
     foreach (object attribute in attributes) 
     { 
      if (attribute is EdmScalarPropertyAttribute) 
      { 
       if ((attribute as EdmScalarPropertyAttribute).EntityKeyProperty == true) 
        return pI; 
      } 
      else if (attribute is ColumnAttribute) 
      { 

       if ((attribute as ColumnAttribute).IsPrimaryKey == true) 
        return pI; 
      } 
     } 
    } 
    return null; 
} 

मुझे आशा है कि यह किसी और की मदद करेगा। मैं बस इतना कह सकता हूं कि यह कैसे करना है इस पर थोड़ा स्पष्ट होना चाहिए।

+1

मुझे लगता है कि यह यह था: http://www.guerrillasyntax.com/index.php/2010/04/24/linq-to-entity-generic-repository/ –

+0

वह था। अच्छी खोज –

+3

तकनीकी रूप से मान्य नहीं है, क्योंकि यदि कोई समग्र प्राथमिक कुंजी है तो यह गलत परिणाम देगा। – Nuzzolilo

15

चल रहा है देने के लिए एक संपत्ति नहीं है प्रत्येक पर ईएफ 4 इकाई को EntityKey कहा जाता है जिसमें EntityKeyValues की सरणी होती है (सरणी यौगिक कुंजी के मामले में होती है)।

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

संपादित: EntityKeyValue एक KeyValuePair<TKey, TValue> वह जगह है जहाँ key संस्था की प्राथमिक कुंजी क्षेत्र है और value जुड़े मूल्य है।

उदा।, मेरे पास Company नामक एक इकाई है जिसका प्राथमिक कुंजी फ़ील्ड Symbol है।

var firstCompany = (from c in context.Companies select c).FirstOrDefault(); 
var kvp = firstCompany.EntityKey.EntityKeyValues[0]; 
// kvp shows {[Symbol, FOO]} 

मेरी सैंडबॉक्स में, मैंने देखा है इस संपत्ति null जब मैं कोड में इकाई बनाया गया था। लेकिन एक बार जब मैं डेटाबेस से इकाई को पढ़ता हूं, तो यह सही ढंग से आबादी वाला था। इसलिए, ऐसा प्रतीत होता है कि एक प्राथमिक कुंजी की ईएफ 4 अवधारणा केवल डेटाबेस को हिट करने के बाद ही खेलती है। हालांकि, यदि आप चाहें तो इसे स्पष्ट रूप से समय से पहले सेट करने के लिए स्वतंत्र हैं।

+0

तुम भी context.Companies.EntitySet.ElementType.KeyMembers –

+2

कोशिश कर सकते हैं कैसे मैं उस संपत्ति नहीं है? –

+4

यदि कोई इस देर से आ रहा है ...EntityKey केवल उन वस्तुओं पर मौजूद है जो EntityObject से प्राप्त होते हैं; केवल वे लोग जो मॉडल-प्रथम सामान हैं। –

2

यह अनिवार्य रूप से लंबा लगता है? मैं एक ही जरूरत पड़ा है, और ऊपर दिए गए सुझावों (SethO और denis_n द्वारा) का उपयोग कर, मैं उपयोग कर रहा हूँ:

 //get the primary key field name and location for the table 
     var primaryFieldName = entry.EntitySet.ElementType.KeyMembers[0].Name ; 
     int primaryFieldLocation = entry.CurrentValues.GetOrdinal(primaryFieldName); 
     //gets the value pair for the primary key (returns field name + value) 
     var primaryField = entry.EntityKey.EntityKeyValues[primaryFieldLocation]; 
     String primaryFieldValue = primaryField.Value.ToString(); 

आशा इस जो कोई रुचि रखता है में मदद करता है

+2

"प्रविष्टि" मान कॉलम नाम है? –

+0

@rana आप मान रहे हैं कि केवल एक कॉलम प्राथमिक कुंजी है –

1

मैं बहुत से लोगों को इस पोस्ट से रोक मान सिर्फ "प्राथमिकता फ्रेमवर्क को प्राथमिक कुंजी कैसे ढूंढें" देखकर? भले ही ईएफ संस्करण (मेरे जैसा)। इसलिए मैं यह उल्लेख करना चाहता था कि ईएफ 6.1 के साथ, आप प्राथमिक कुंजी प्राप्त करने के लिए एक एक्सटेंशन विधियां भी बना सकते हैं। उदाहरण निम्नलिखित है और पूरी तरह से ठीक काम करता है।

पीएस: मैं 100% निश्चित नहीं हूं, अगर यह संयुक्त और यौगिक कुंजी के साथ काम करेगा।

using System; 
using System.Data.Entity; 
using System.Data.Entity.Core.Metadata.Edm; 
using System.Data.Entity.Infrastructure; 
using System.Linq; 

namespace System.Data.Entity 
{ 
    public static class DbContextExtensions 
    { 
     public static string[] GetKeyNames<TEntity>(this DbContext context) 
      where TEntity : class 
     { 
      return context.GetKeyNames(typeof(TEntity)); 
     } 

     public static string[] GetKeyNames(this DbContext context, Type entityType) 
     { 
      var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; 

      // Get the mapping between CLR types and metadata OSpace 
      var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace)); 

      // Get metadata for given CLR type 
      var entityMetadata = metadata 
        .GetItems<EntityType>(DataSpace.OSpace) 
        .Single(e => objectItemCollection.GetClrType(e) == entityType); 

      return entityMetadata.KeyProperties.Select(p => p.Name).ToArray(); 
     } 
    } 
} 

Original Source

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