Linq To Sql進階系列(七)動態查詢續及CLR與SQL在某些細節上的差別

作者: Tom Song  來源: 博客園  發布時間: 2008-09-27 12:04  閱讀: 16517 次  推薦: 0   原文鏈接   [收藏]  
 

系列文章導航:

Linq To Sql進階系列(一)從映射講起

Linq To Sql進階系列(二)M:M關系

Linq To Sql進階系列(三)CUD和Log

Linq To Sql進階系列(四)User Define Function篇

Linq To Sql進階系列(五)Store Procedure篇

Linq To Sql進階系列(六)用object的動態查詢與保存log篇

Linq To Sql進階系列(七)動態查詢續及CLR與SQL在某些細節上的差別

 

在上面一篇文章Linq To Sql進階系列(六)中,我們提到了使用object的動態查詢。本文在上文的基礎上,再做更加深入的引申。同時修正上文中一些不妥的地方。

1, object的動態查詢續
首先要做的事情,就是將Find的函數改成擴展方法。擴展方法只能放在靜態類里,而且它的第一個參數必須帶this關鍵字。在上文中,作者留下了一個迷題。當需要or條件時,又該如何做呢?本文也將這個問題給出回答。但是對于動態Like的條件,筆者依然還沒有找到一個較好的方法。為了增加or條件,函數的聲明也再一次被改動。如下:
    public static IQueryable<TEntity> Find<TEntity>(this IQueryable<TEntity> source, TEntity obj, bool isAnd) where TEntity : class
在上文中,我們還碰到了System.Nullable<int>此類類型不支持的問題。其實這個地方主要原因在于我們構造right端的Expression Tree時,沒有給它參數。那么這個問題通過Expression right = Expression.Constant(p.GetValue(obj, null), p.PropertyType); 可以得到修復。那整個函數修改后,如下:

    public static IQueryable<TEntity> Find<TEntity>(this IQueryable<TEntity> source, TEntity obj,
bool isAnd) where TEntity : class
    {
        
if (source == null)
            
throw new ArgumentNullException("Source can't be null!!");
        
//獲得所有property的信息
        PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Public |
BindingFlags.Instance);

        Expression condition 
= null;
        
//先構造了一個ParameterExpression對象,這里的c,就是Lambda表達中的參數。(c=>)  
        
//本變量被移出了foreach循環
        ParameterExpression param = Expression.Parameter(typeof(TEntity), "c");
        
//遍歷每個property
        foreach (PropertyInfo p in properties)
        
{
            
if (p != null)
            
{
                Type t 
= p.PropertyType;
                
//只支持value型和string型的影射
                if (t.IsValueType || t == typeof(string))
                
{
                    
//如果不為null才算做條件
                    if (p.GetValue(obj, null!= null)
                    
{
                        
//SQL Server does not support comparison of TEXT, NTEXT, XML and IMAGE ,etc
                        ///Only support BigInt,Bit,Char,Decimal,Money,NChar,Real,
                        
///Int,VarChar,SmallMoney,SmallInt,NVarChar,NVarChar(MAX),VarChar(MAX)

                        Attribute attr = Attribute.GetCustomAttribute(p, typeof(ColumnAttribute));
                        
if (attr != null)
                        
{
                            
string dbType = (attr as ColumnAttribute).DbType;
                            
if (dbType.Contains("Text"|| dbType.Contains("NText")
                                
|| dbType.Contains("Xml"|| dbType.Contains("Image")
                                
|| dbType.Contains("Binary"|| dbType.Contains("DateTime")
                                
|| dbType.Contains("sql_variant"|| dbType.Contains("rowversion")
                                
|| dbType.Contains("UniqueIdentifier"|| dbType.Contains
(
"VarBinary(MAX)"))
                            
{
                                
continue;
                            }

                        }
 
                        
//構造表達式的右邊,值的一邊
                        Expression right = Expression.Constant(p.GetValue(obj, null), p.PropertyType);
                        
//構造表達式的左邊,property一端。
                        Expression left = Expression.Property(param, p.Name);
                        
//生成篩選表達式。即c.CustomerID == "Tom"
                        Expression filter = Expression.Equal(left, right);
                        
if (condition == null)
                        
{
                            condition 
= filter;
                        }

                        else
                        {
                            
if (isAnd)
                                condition 
= Expression.And(condition, filter);
                            
else
                                condition = Expression.Or(condition, filter);
                        }

                    }

                }

            }

        }

        if (condition != null)
        
{
            Expression
<Func<TEntity, bool>> pred = Expression.Lambda<Func<TEntity, bool>>(condition, param);
            
return source.Where(pred);
        }
  
        
return source;
        
    }

    

 

0
0
 
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()