LINQ中怎么动态修改表名称,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
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中怎么动态修改表名称问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网行业资讯频道了解更多相关知识。