Linq To SQL下实现动态表名的映射2011-10-15 博客园 麦舒提出问题前段时间,在博客园里看到有位朋友,问如何实现在动态表名。我们都知道,把一个实体类映谢到表 里,应该这样写:
[Table(Name = "User")]
class User
{
[Column]
public int ID;
[Column]
public string Name;
}
很明显,这里的表名是写死的,有些时候,我们可能要根据不同的情况实现不同的表名 里加个前缀或者后缀,例如:tt_User,aa_User,User1、User2。分析问题要解决这个问题,首先我们就要明白一个问题,DataContext是如何将实体到表的映射的,事实上,它 是例用MappingSource提供的信息来进行映射的。要解决上面的问题,我就是需要重新构一个继承于 MappingSource的类。解决问题代码如下:
using System;using System.Collections.Generic;using System.Data.Linq;using System.Data.Linq.Mapping;using System.Diagnostics;using System.Globalization;using System.Linq;using System.Reflection;using System.Text;using System.Xml.Schema;namespace ALinq.Mapping{class DynamicMappingSource : MappingSource{class DynamicAttributedMetaModel : MetaModel{private MetaModel source;private const string TypeName = "System.Data.Linq.Mapping.AttributedMetaModel";private DynamicMappingSource mappingSource;internal DynamicAttributedMetaModel(MappingSource mappingSource, Type contextType){this.mappingSource = (DynamicMappingSource)mappingSource;var bf = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance;var args = new object[] { mappingSource, contextType };source = typeof(DataContext).Assembly.CreateInstance(TypeName, false, bf, null, args, CultureInfo.CurrentCulture, null) as MetaModel;Debug.Assert(source != null);}public override MetaTable GetTable(Type rowType){if (mappingSource.GetMetaTableName != null){var typeName = "System.Data.Linq.Mapping.AttributedMetaTable";var bf = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance;var attribute = new TableAttribute { Name = mappingSource.GetMetaTableName(rowType) };var args = new object[] { source, attribute, rowType };var metaTable = typeof(DataContext).Assembly.CreateInstance(typeName, false, bf, null,args, CultureInfo.CurrentCulture, null) as MetaTable;return metaTable;}return source.GetTable(rowType);}public override MetaFunction GetFunction(MethodInfo method){return source.GetFunction(method);}public override IEnumerable<MetaTable> GetTables(){return source.GetTables();}public override IEnumerable<MetaFunction> GetFunctions(){return source.GetFunctions();}public override MetaType GetMetaType(Type type){return source.GetMetaType(type);}public override MappingSource MappingSource{get { return source.MappingSource; }}public override Type ContextType{get { return source.ContextType; }}public override string DatabaseName{get { return source.DatabaseName; }}public override Type ProviderType{get { return source.ProviderType; }}}public Func<Type, string> GetMetaTableName;protected override MetaModel CreateModel(Type dataContextType){if (dataContextType == null){throw new ArgumentNullException("dataContextType");}return new DynamicAttributedMetaModel(this, dataContextType);}}[Table(Name = "User")]class User{[Column]public int ID;[Column]public string Name;}class Program{static void Main(string[] args){var mappingSource = new DynamicMappingSource();int i = 0;mappingSource.GetMetaTableName = delegate(Type type) { var att = type.GetCustomAttributes(typeof(TableAttribute), true).Single()as TableAttribute; Debug.Assert(att != null); return att.Name + i; };var constr = @"Data Source=NOTEBOOKSQLEXPRESS;Initial Catalog=DemoDataContext;Integrated Security=True";var context = new DataContext(constr, mappingSource) { Log = Console.Out };i = 1;context.GetTable<User>().Select(o => o).ToList();i = 2;context.GetTable<User>().Select(o => o).ToList();}}}