Entity Framework 4.0 - Get By ID с использованием обобщений и отражений - PullRequest
3 голосов
/ 28 июля 2010

Я ищу возможность загрузки сущности по идентификатору с использованием обобщений и отражения свойств, но не уверен, как выполнить эту задачу с помощью Entity Framework 4.0.

У меня есть метод в моем абстрактном методе как таковой:

public abstract T GetById(object id, TestContext context);

В настоящее время, поскольку он является абстрактным, я должен реализовать этот метод в каждом отдельном классе репозитория, который я создаю как таковой:

public override TestObject GetById(object id, TestContext context)
{
    return context.TestObject.First(x => x.TestId == (int) id);
}

Есть ли способ выполнить эту же задачу с помощью рефлексии и обобщений в моем абстрактном классе?

Ответы [ 3 ]

2 голосов
/ 29 июля 2010

Это пример VB, который я использую. Все мои ключи - это GUID, но вы, вероятно, можете это изменить.

Public Shared Function GetKeyPropertyName(ByVal typeName As String) As String
    Dim props = Type.GetType(typeName).GetProperties
    For Each prop In props
        Dim atts = prop.GetCustomAttributes(True)
        For Each att In atts
            If TypeOf (att) Is EdmScalarPropertyAttribute Then
                If DirectCast(att, EdmScalarPropertyAttribute).EntityKeyProperty Then
                    Return prop.Name
                End If
            End If
        Next
    Next
    Throw New ApplicationException(String.Format("No key property found for type '{0}'.", typeName))
End Function

Public Shared Function GetObjectById(Of T As EntityObject)(ByVal id As Guid) As T
    Dim ctx = MyContext
    Dim entityType As Type = GetType(T)
    Dim entityTypeName As String = entityType.ToString
    Dim keyProperty As String = GetKeyPropertyName(entityTypeName)

    Dim container = ctx.MetadataWorkspace.GetEntityContainer(ctx.DefaultContainerName, Metadata.Edm.DataSpace.CSpace)

    Dim entitySetName As String = (From meta In container.BaseEntitySets Where meta.ElementType.FullName = entityTypeName Select meta.Name).First()
    Dim entitySetFullName As String = String.Format("{0}.{1}", container.Name, entitySetName)


    Dim entityKeyValues As IEnumerable(Of KeyValuePair(Of String, Object)) = _
        New KeyValuePair(Of String, Object)() {New KeyValuePair(Of String, Object)(keyProperty, id)}

    Dim key As New EntityKey(entitySetFullName, entityKeyValues)
    Return DirectCast(ctx.GetObjectByKey(key), T)
End Function
0 голосов
/ 12 апреля 2012

Я хотел бы рекомендовать альтернативную версию, состоящую только из GetObjectById, как рекомендовано Биллом Дейли, проблема в том, что этот метод вызовет исключение, если не существует объекта с данным Id. Это все прекрасно, если вы ожидаете найти свой объект, но в противном случае вы, вероятно, хотели бы получить вместо него нулевую ссылку. Я использую следующий код, который предполагает, что модель имеет свойство с именем Id. Я использую дополнительный метод, чтобы проверить это в конструкторе хранилища.

public Repository(...)
{
    // code...
    GetByIdAccepted = ExamineIdKey();
}

protected bool ExamineIdKey()
{
    // Fetch the type and look for an "Id"-member
    return typeof(TModel).GetMember("Id", BindingFlags.Instance | BindingFlags.Public).Length > 0;
}

public TModel GetById(object id)
{
    // Validate that GetById is ok for our given model
    if(!GetByIdAccepted)
        throw new InvalidOperationException("error text");

    object model;
    if (Connection.TryGetObjectByKey(new EntityKey(EntityName, "Id", id), out model))
        return (TModel)model;

    return null;
}
0 голосов
/ 19 января 2011

Вы можете адаптировать этот метод расширения:

 public static T GetById<T, Y>(this ObjectSet<T> entitySet, Y Id) 
        where T : EntityObject 

    {
        return entitySet.Where(
                e => 
                    e.EntityKey.EntityKeyValues.Select(
                        v => EqualityComparer<Y>.Default.Equals((Y)v.Value, Id)
                    ).Count() > 0)
                .First();            
    }

Я никогда не пробовал этого в каких-либо сложных сценариях, поэтому UAYOR.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...