Using reflection to address a Linqed property

后端 未结 3 2043
青春惊慌失措
青春惊慌失措 2021-01-03 17:22

I\'m trying to writing a generic method that will load a record of a specific type, with a specific ID. Here\'s one way that works:

    public abstract clas         


        
相关标签:
3条回答
  • 2021-01-03 18:03

    Having read these posts: Generic Data Access using LINQ to SQL and C#, LINQ-to-SQL: Generic Primary Key function and Calling a generic method with Type

    My colleague and I came up with the following digest:

    We added the following method to our datacontext (in a partial class).

    public T GetInstanceByPrimaryKey<T>(object primaryKeyValue) where T : class
    {
        var table = this.GetTable<T>();
        var mapping = this.Mapping.GetTable(typeof(T));
        var pkfield = mapping.RowType.DataMembers.SingleOrDefault(d => d.IsPrimaryKey);
    
        if (pkfield == null)
            throw new Exception(String.Format("Table {0} does not contain a Primary Key field", mapping.TableName));
    
        var param = Expression.Parameter(typeof(T), "e");
    
        var predicate =
            Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(param, pkfield.Name), Expression.Constant(primaryKeyValue)), param);
    
        return table.SingleOrDefault(predicate);
    }
    

    Then, where we need to instanciate from the type name and primary key value:

    string name = "LinqObjectName";
    int primaryKey = 123;
    
    var dc = new YourDataContext();
    
    Type dcType = dc.GetType();
    Type type = dcType.Assembly.GetType(String.Format("{0}.{1}", dcType.Namespace, name));
    
    MethodInfo methodInfoOfMethodToExcute = dc.GetType().GetMethod("GetInstanceByPrimaryKey");
    MethodInfo methodInfoOfTypeToGet = methodInfoOfMethodToExcute.MakeGenericMethod(name);
    var instance = methodInfoOfTypeToGet.Invoke(dc, new object[] { primaryKey });
    
    return instance;
    

    Hope this helps!

    0 讨论(0)
  • 2021-01-03 18:05

    Linq to SQL tries to translate your linq-query into SQL, but it does not know how to translate your property to a column name in the DB.

    A good explanation can be found here on SO: simple linq to sql has no supported translation to SQL

    But how to solve it, is another matter. I have with succes used the apporoach from this thread:

    http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/df9dba6e-4615-478d-9d8a-9fd80c941ea2/

    Or you can use dynamic query as mentioned here by scott guthrie:

    http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

    0 讨论(0)
  • 2021-01-03 18:06

    Since LINQ statements referred to a LINQ-to-SQL IQueryable are translated to SQL queries, you will have to use the AsEnumerable extension (which will in turn cause a read of all the items in the database) and do reflection-related stuff on that IEnumerable.
    EDIT
    As required here's a clarification
    As specified in a comment, what I meant was something like:

     (from obj in context.GetTable<T>() select obj).AsEnumerable().Where(x => x.IDValue == ID)

    Unlike a query executed on an IQueryable, which can be perfectly translated to SQL such as

    
    context.GetTable().Where(x => x.Text == "Hello")
    which gets converted to something similar to

    SELECT * FROM TABLE_MAPPED_TO_TYPE_T WHERE Text = 'Hello'

    a query executed against an IEnumerable - in your case - will be executed by fetching all the entries of your table and then applying code-wise the specified filter.

    0 讨论(0)
提交回复
热议问题