2013-11-27 3 views
0

Учитывая объект, я хотел бы получить первичные ключи связанных объектов в общем виде. Например: для Клиента я хотел бы иметь список идентификаторов его ордеров.Общий способ получения первичных ключей из свойств навигации

Текущая подпись моей попытки:

GetPrimaryKeysOfRelatedEntities(DbContext db, object entity) 

Я могу получить рК сущности, и я в состоянии получить навигационные свойства объекта ... но я не могу получить PK навигационных свойств объекта.

У меня отсутствует небольшая ссылка здесь!

Вот мой код, чтобы получить ключи сущностей, которые не работают для навигационных свойств

private static IEnumerable<string> GetEntityType(DbContext db, Type entityType) 
{ 
    entityType = ObjectContext.GetObjectType(entityType); 

    var metadataWorkspace = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace; 
    var objectItemCollection = (ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace); 

    ReadOnlyCollection<EntityType> entityTypes = metadataWorkspace.GetItems<EntityType>(DataSpace.OSpace); 

    if (entityTypes == null) 
    { 
     throw new InvalidOperationException(); 
    } 

    var ospaceType = entityTypes.SingleOrDefault(t => objectItemCollection.GetClrType(t) == entityType); 

    if (ospaceType == null) 
    { 
     throw new ArgumentException(
      string.Format("The type '{0}' is not mapped as an entity type.", entityType.Name), "entityType"); 
    } 

    return ospaceType.KeyMembers.Select(k => k.Name); 
} 

Этот код использует EntityType, и я Propably должен использовать что-то другое, но я не уверен, что.

ответ

1

Я не вижу проблемы, у вас есть отличный кусок кода, который может получить первичные ключи объекта по типу.

Вы можете использовать отражение, чтобы перечислять свойства вашего объекта и вызывать свой код для типа этих свойств. Для экс как это:

var entityType = entity.GetType(); // or another type source 
foreach (var prop in type.GetProperties()) 
{ 
    if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericArguments().Any(x => x.Assembly == type.Assembly)) 
    { 
     var navPropType = prop.PropertyType.GetGenericArguments().First(x => x.Assembly == type.Assembly); 
     var keysForThisNavPropType = GetEntityType(db, navPropType); 
    } 
    else if (prop.PropertyType.Assembly == type.Assembly) 
    { 
     var keysForThisNavPropType = GetEntityType(db, prop.PropertyType); 
    } 
} 

Как вы можете увидеть критерий для поиска навигационных свойств является то, что его содержащим Собранием одно и то же в качестве основного типа.

Редактировать

Хорошо, попробуйте следующее:

 // we need DbContext vaule 
     var db = YOUR_DB_CONTEXT; // assing db context here 
     // So we can get ObjectContext instance 
     var ctx = ((IObjectContextAdapter) db).ObjectContext; 
     // we need some entity to check 
     object entity = someYourEntity; // assign your entity here 
     // let's get its type 
     var type = entity.GetType(); 

     // helper function to get set name 
     Func<Type, ObjectContext, string> getEntitySetByObjectType = (t, context) => 
      { 
       var container = 
        context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace); 

       var entitySet = 
        container.BaseEntitySets.First(item => item.ElementType.Name.Equals(t.Name)); 

       return container.Name + "." + entitySet.Name; 
      }; 

     // go through the entity's properties 
     foreach (var prop in type.GetProperties()) 
     { 
      // nav properties which are collections 
      if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericArguments().Any(x => x.Assembly == type.Assembly)) 
      { 
       var val = (IEnumerable)prop.GetValue(entity); 
       if (val != null) 
       { 
        // get value and check if it is not null 
        string setName = null; 
        // go through collection values 
        foreach (var obj in val) 
        { 
         if (setName == null) 
          setName = getEntitySetByObjectType(obj.GetType(), ctx); 

         // get primary key values 
         var entityKey = ctx.CreateEntityKey(setName, obj); 
         Console.WriteLine(entityKey); 
        } 
       } 
      } 
      // nav props which are single objects 
      else if (prop.PropertyType.Assembly == type.Assembly) 
      { 
       // get value and check if it is not null 
       var val = prop.GetValue(entity); 
       if (val != null) 
       { 
        // get primary key values 
        var entityKey = ctx.CreateEntityKey(getEntitySetByObjectType(prop.PropertyType, ctx), val); 
        Console.WriteLine(entityKey); 
       } 
      } 
     } 

метод CreateEntityKey возвращает объект класса EntityKey (http://msdn.microsoft.com/ru-ru/library/system.data.entitykey(v=vs.110).aspx), который имеет EntityKeyValues ​​свойство, которое является массивом EntityKeyMember. EntityKeyMember имеет свойства Key и Value, которые являются точно первичным именем и значением ключа.

+0

Tnx для вашего ответа. С вашим кодом я могу получить имя идентификатора свойства навигации, но не его значение. Когда я пытаюсь получить entityEntry, используя Context.Entry (entity), он терпит неудачу. Я борюсь с передачей правильного типа. – Jowen

+0

Jowen, если вам нужно значение, которое вы можете получить от объекта, выполните следующие действия: navEntity = prop.GetValue (объект, null), а затем Context.Entry (navEntity). Или я что-то неправильно понимаю? – Tony

+0

Возможно, это так просто, как вы думаете, но я все еще не могу заставить его работать. Я получаю сообщение об ошибке при попытке заполнить navEntity. Это слишком много усилий, чтобы написать весь метод? Я бы очень признателен! – Jowen

 Смежные вопросы

  • Нет связанных вопросов^_^