开发者

Linq2SQL - selecting items using reflection

I'm trying to load a collection of entities using Linq2SQL. The problem is, I dont know what the entities are,IList<object>. I have tried to select them using reflection, but I get an out of memory error when I do the select, I presume because the context is unable to parse my expression,and is loading everything from the DB.

If anyone has any advice on this, or an alternative way to do what I want, please let me know.

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(开发者_StackOverflow).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();
}


By using a delegate you are forcing it to use LINQ-to-Objects, which is why it is running out of memory. What you need to do is build an Expression instead. Equally, it is bad practice to use the attributes as that is not the only model that LINQ-to-SQL supports; it is preferable to look at dataContext.Mapping.GetMetaType(entityType) to get the primary key.

If you have 4.0, the following should work:

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);

with

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);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜