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

發表于:2008-05-07來源:作者:點擊數: 標簽:sqlSQLSqlLinqCLR
在上面一篇文章Linq To Sql進階系列(六)中,我們提到了使用object的動態查詢。本文在上文的基礎上,再做更加深入的引申。同時修正上文中一些不妥的地方。 1, object的動態查詢續 首先要做的事情,就是將Find的函數改成擴展方法。擴展方法只能放在靜態類里
 在上面一篇文章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; }
  在這里,首先檢查輸入的參數是否為null。擴展方法其實是按靜態方法執行的。它和靜態方法唯一不同的就是系統自動為其加了一個Attribute,而這個Attribute只能通過在第一個參數加this關鍵字才能獲得。而后,在影射類型上,修改后的函數只支持數值型和string型。其原因就是像 imager等并不支持條件查詢。為了簡化,我們只支持數值型和string型。這里最大的變化莫過于支持or條件了。調用Expression.And 或Expression.Or就可以了。還有一個變化就是ParameterExpression對象和xpression<Func< TEntity, bool>>被移出了foreach循環。這樣,提高了效率,只是在最后才去生成條件。
  而實際上,大家大多使用是and條件,那再重載一個方法。
public static IQueryable<TEntity> Find<TEntity>(this IQueryable<TEntity> source, TEntity obj) where TEntity : class { return Find<TEntity>(source,obj,true);

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97