Linq2SQL - выбор элементов с использованием отражения - PullRequest
3 голосов
/ 06 июля 2011

Я пытаюсь загрузить коллекцию сущностей, используя Linq2SQL.Проблема в том, что я не знаю, что это за сущности, IList<object>.Я попытался выбрать их с помощью отражения, но я получаю ошибку нехватки памяти, когда я делаю выбор, я предполагаю, потому что контекст не может проанализировать мое выражение и загружает все из БД.

Если у кого-нибудь есть какие-либо советы по этому поводу или другой способ сделать то, что я хочу, пожалуйста, дайте мне знать.

foreach (object entity in requiredEntities)
{
   Type entityType = entity.GetType();
   IQueryable<object> entityTable = (IQueryable<object>)dataContext.GetTable(entityType);               

   // grab the objects primary key field
   var pkeyField = entityType.GetProperties().SingleOrDefault(p =>
                   p.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute),true)
                   .Cast<System.Data.Linq.Mapping.ColumnAttribute>() 
                   .Any(attrib => attrib.IsPrimaryKey));

   object pkeyValue = pkeyField.GetValue(entity,null);

   Func<object,bool> primaryKeySelector = o => pkeyField.GetValue(o,null) == pkeyValue;

   // crash here, out of memory exception
   object result = entityTable.Where(primaryKeySelector).SingleOrDefault();
}

1 Ответ

4 голосов
/ 06 июля 2011

Используя делегата, вы заставляете его использовать LINQ-to-Objects, поэтому ему не хватает памяти. Что вам нужно сделать, это построить Expression вместо этого. В равной степени плохая практика - использовать атрибуты, поскольку это не единственная модель, поддерживаемая LINQ-to-SQL; предпочтительнее взглянуть на dataContext.Mapping.GetMetaType(entityType), чтобы получить первичный ключ.

Если у вас 4.0, должно работать следующее:

var entityType = typeof(User);
var metaType = dataContext.Mapping.GetMetaType(entityType);
var member = metaType.DataMembers.Single(m => m.IsPrimaryKey).Member;

var param = Expression.Parameter(entityType);
var body = Expression.Equal(Expression.MakeMemberAccess(param, member),
    Expression.MakeMemberAccess(Expression.Constant(entity), member));
dynamic table = dataContext.GetTable(entityType);

object result = Cheeky(table, body, param);

с

static T Cheeky<T>(ITable<T> source, Expression body, ParameterExpression param)
    where T : class
{
    var predicate = Expression.Lambda<Func<T, bool>>(body, param);
    return source.SingleOrDefault(predicate);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...