C# LINQ to SQL: Refactoring this Generic GetByID method

前端 未结 6 1676
故里飘歌
故里飘歌 2020-11-30 02:03

I wrote the following method.

public T GetByID(int id)
{
    var dbcontext = DB;
    var table = dbcontext.GetTable();
    return table.ToList().Sin         


        
6条回答
  •  广开言路
    2020-11-30 02:32

    What you need is to build an expression tree that LINQ to SQL can understand. Assuming your "id" property is always named "id":

    public virtual T GetById(short id)
    {
        var itemParameter = Expression.Parameter(typeof(T), "item");
        var whereExpression = Expression.Lambda>
            (
            Expression.Equal(
                Expression.Property(
                    itemParameter,
                    "id"
                    ),
                Expression.Constant(id)
                ),
            new[] { itemParameter }
            );
        var table = DB.GetTable();
        return table.Where(whereExpression).Single();
    }
    

    This should do the trick. It was shamelessly borrowed from this blog. This is basically what LINQ to SQL does when you write a query like

    var Q = from t in Context.GetTable

    You just do the work for LTS because the compiler cannot create that for you, since nothing can enforce that T has an "id" property, and you cannot map an arbitrary "id" property from an interface to the database.

    ==== UPDATE ====

    OK, here's a simple implementation for finding the primary key name, assuming there is only one (not a composite primary key), and assuming all is well type-wise (that is, your primary key is compatible with the "short" type you use in the GetById function):

    public virtual T GetById(short id)
    {
        var itemParameter = Expression.Parameter(typeof(T), "item");
        var whereExpression = Expression.Lambda>
            (
            Expression.Equal(
                Expression.Property(
                    itemParameter,
                    GetPrimaryKeyName()
                    ),
                Expression.Constant(id)
                ),
            new[] { itemParameter }
            );
        var table = DB.GetTable();
        return table.Where(whereExpression).Single();
    }
    
    
    public string GetPrimaryKeyName()
    {
        var type = Mapping.GetMetaType(typeof(T));
    
        var PK = (from m in type.DataMembers
                  where m.IsPrimaryKey
                  select m).Single();
        return PK.Name;
    }
    

提交回复
热议问题