LINQ TO SQL动态修改表名称的实现浅析

开发 后端
LINQ TO SQL动态修改表名称的实现的过程是什么呢?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  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

dnt_users是数据库中的物理表.而我们的产品有一个特性,就是允许用户定制表名称的前缀.其实"dnt_"就是表的前缀名.而这个值(前缀)是通过产品中的Tableprefix属性获取的.Tableprefix属性返回的值是通过dnt.config中配置的.

所以这就要求在程序运行时动态加载表(前缀)名称.所在本人在网上开始四处找这方面的文章和资料.但找到的并不是特别对症。因为才自己动手实验一下,看看有什么好方法:)

LINQ TO SQL动态修改表名称尝试1:

通过常量方式将表属性[Table(Name="dbo.dnt_users")]替换成:

[Table(Name="dbo." + DntDataContext.tableprefix +"users")] 
  • 1.

而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_";  
 
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

虽然这种方式将前台的名称抽取出来,将因为是采用常量方式,所以无法进行动态绑定.所以这次尝试是失败的.

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); 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

上面代码段的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);  
 }  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

前端使用代码如下:

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();  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

当然数据库链接对象可以封装到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();  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

返回的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);  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

我想应该可以在这里完成相应的表名称的替换,实现起来也很容易.经过这一番折腾,我发现如果LINQ TO SQL 支持通过XML配置文件进行绑定才是最终的理想方案.因为本人又开始四处搜索这方面的信息,发现了这篇文章:)原来还真有,只是自己刚入门心急不知道,所以才兜了这么一大圈.看来以后还要认真耐心看文档和相应的方法提示了, 好在这种低级错误也不是犯过一次两次了:)

LINQ TO SQL动态修改表名称的实现基本内容就向你介绍到这里,希望对你了解和学习使用LINQ TO SQL动态修改表名称有所帮助。

【编辑推荐】

  1. LINQ嵌套查询实现浅析
  2. LINQ查询方式的探寻
  3. LINQ查询的效果分析
  4. LINQ查询和泛型类型的关系浅析
  5. LINQ动态查询的实现浅析
责任编辑:仲衡 来源: ittang.com
相关推荐

2009-09-14 19:14:51

LINQ动态查询

2009-09-14 09:46:00

LINQ to SQL

2009-09-17 17:34:23

linq to sql

2009-09-15 09:19:22

linq动态条件

2009-09-16 17:11:35

LINQ To SQL

2009-09-10 18:02:23

LINQ to SQL

2009-09-17 18:05:15

linq to sql

2009-09-15 10:12:37

LINQ To SQL

2009-09-14 17:40:47

LINQ To SQL

2009-09-14 16:29:39

LINQ嵌套

2009-09-14 18:23:59

LINQ嵌套查询

2009-09-10 10:09:46

LINQ to SQL

2009-09-17 08:47:00

Linq插入数据

2009-09-18 15:15:12

LINQ to SQL

2009-09-17 16:46:34

Linq to sql

2009-09-18 14:25:36

LINQ to SQL

2011-04-07 14:04:28

SQL动态交叉表

2009-12-23 09:04:41

LINQ通用分页

2009-09-14 19:55:03

LINQ事务处理

2009-09-15 14:30:11

Linq连接
点赞
收藏

51CTO技术栈公众号