LINQ TO SQL動態修改表名稱的實現淺析
LINQ TO SQL動態修改表名稱的實現是如何的呢?我們在實際的操作過程中如何實現呢?需要注意什么呢?那么這里向你詳細說明一下,希望對你有所幫助。
LINQ TO SQL動態修改表名稱的操作:
最近有點空閑時間,抽空看了一下LINQ方面的東西。好在園子里這方面的系列文章很多. 免去了不少查找的時間. 因為本人習慣于學完就動手嘗試,而我們的產品中也都將訪問數據庫的SQL語句統一封裝進了DLL.所以就想先拿產品練一下手:)
但萬事開頭難,一用上才發現有一個不大不小的問題擋在了面前.就是使用LINQ TO SQL模板生成代碼后,會在相應的數據庫實體類上綁定一個tablename屬性.如下代碼:
- [Table(Name="dbo.dnt_users")]
- public partial class Userinfo :
- INotifyPropertyChanging,
- INotifyPropertyChanged
- {
dnt_users是數據庫中的物理表.而我們的產品有一個特性,就是允許用戶定制表名稱的前綴.其實"dnt_"就是表的前綴名.而這個值(前綴)是通過產品中的Tableprefix屬性獲取的.Tableprefix屬性返回的值是通過dnt.config中配置的.
所以這就要求在程序運行時動態加載表(前綴)名稱.所在本人在網上開始四處找這方面的文章和資料.但找到的并不是特別對癥。因為才自己動手實驗一下,看看有什么好方法:)
LINQ TO SQL動態修改表名稱嘗試1:
通過常量方式將表屬性[Table(Name="dbo.dnt_users")]替換成:
- [Table(Name="dbo." + DntDataContext.tableprefix +"users")]
而tabalprefix定義如下:
- public const string tableprefix = "dnt_";
- [System.Data.Linq.Mapping.
- DatabaseAttribute(Name="dnt_2")]
- public partial class DntDataContext :
- System.Data.Linq.DataContext
- {
- public const string tableprefix = "dnt_";
- }
雖然這種方式將前臺的名稱抽取出來,將因為是采用常量方式,所以無法進行動態綁定.所以這次嘗試是失敗的.
LINQ TO SQL動態修改表名稱嘗試2:
替換DataContext生成的CommandText內容因為LINQ TO SQL最終還是被翻譯成SQL,所以本人又使用下面的方法進行測試:
- DntDataContext ddc = new DntDataContext();
- var exp = from u in ddc.Userinfo
- orderby u.uid ascending
- select u
- string query =
- ddc.GetCommand(exp).CommandText.Replace("dnt_", "daizhj_");
- var result = ddc.ExecuteQuery<Userinfo>(query, 0);
- Console.WriteLine(((Userinfo[])
- result.ToArray())[0].username);
上面代碼段的ddc.GetCommand(exp).CommandText.Replace("dnt_", "daizhj_")是做的這個工作.雖然這次采用替換方式解決了問題.但看了代碼的朋友會發現,代碼變得很丑,本人也是這么看的.即使封裝了也是很難受.沒辦法,放棄:(
LINQ TO SQL動態修改表名稱嘗試3: 繼承并實現IQuerable接口
好在Matt Warren在他的文章中提到過如果建立一個IQueryable Provider(已修改, 更多內容參見這里).另外LoveCherry也將這篇文章翻譯了過來,大家有興趣不妨看一下,很有意思, 詳情點擊這里:)
所以本人就直接使用了他在文中所說的方式.將DNTDataContext做了修改如下:
- [System.Data.Linq.Mapping.DatabaseAttribute(Name="dnt_2")]
- public partial class DntDataContext :
- System.Data.Linq.DataContext
- {
- public Query<Userinfo> Userinfos;
- //該Query繼承自IQueryable
- public DntDataContext(System.Data.IDbConnection connection) :
- base(connection, mappingSource)
- {
- QueryProvider provider =
- new DbQueryProvider((DbConnection)connection);
- this.Userinfos = new Query<Userinfo>(provider);
- }
- }
前端使用代碼如下:
- using (SqlConnection con =
- new SqlConnection(global::Demo.Properties.
- Settings.Default.dnt_2ConnectionString))
- {
- con.Open();
- DntDataContext ddc = new DntDataContext(con);
- IQueryable<Userinfo> query = from u in ddc.Userinfos
- where (u.uid > 1)
- select u;
- foreach (Userinfo user in query.ToArray())
- {
- Console.WriteLine(user.username);
- }
- Console.ReadLine();
- }
當然數據庫鏈接對象可以封裝到DntDataContext中,讓代碼的整體感覺更LINQ一些.相關的代碼下載會在本文結尾處給出,詳見LINQ.KIT代碼中DbQueryProvider.cs文件.(相關修改已通過注釋給出).
這次改動整體上能夠滿足查詢上的需求,但是如果想使用相應的insert,update,delete也能做到相應的表名替換的話,還是要從System.Data.Linq.Table入手.即讓
- using (SqlConnection con = new SqlConnection(
- global::Demo.Properties.Settings.
- Default.dnt_2ConnectionString))
- {
- con.Open();
- DntDataContext ddc = new DntDataContext(con);
- IQueryable<Userinfo> query = from u in ddc.Userinfos
- where (u.uid > 1)
- select u;
- foreach (Userinfo user in query)
- {
- Console.WriteLine(user.username);
- }
- Console.ReadLine();
- }
返回的Userinfo類所綁定的表是被替換完成的表名稱. 因為本人時間和精力有限,無法再去做進一步的研究了.但老趙的這篇文章給了我一些啟發.其中下面的代碼段就是他用來擴展DELETE功能的方法
- public static int Delete<TEntity>
- (this Table<TEntity> table,
- Expression<Func<TEntity, bool>> predicate)
- where TEntity : class
- {
- string tableName =
- table.Context.Mapping.GetTable(
- typeof(TEntity)).TableName;
- string command = String.Format(
- "DELETE FROM {0}", tableName);
- ConditionBuilder conditionBuilder =
- new ConditionBuilder();
- conditionBuilder.Build(predicate.Body);
- if (!String.IsNullOrEmpty(
- conditionBuilder.Condition))
- {
- command += " WHERE " + conditionBuilder.Condition;
- }
- return table.Context.ExecuteCommand(
- command, conditionBuilder.Arguments);
- }
我想應該可以在這里完成相應的表名稱的替換,實現起來也很容易.經過這一番折騰,我發現如果LINQ TO SQL 支持通過XML配置文件進行綁定才是最終的理想方案.因為本人又開始四處搜索這方面的信息,發現了這篇文章:)原來還真有,只是自己剛入門心急不知道,所以才兜了這么一大圈.看來以后還要認真耐心看文檔和相應的方法提示了, 好在這種低級錯誤也不是犯過一次兩次了:)
LINQ TO SQL動態修改表名稱的實現基本內容就向你介紹到這里,希望對你了解和學習使用LINQ TO SQL動態修改表名稱有所幫助。
【編輯推薦】