提出问题
前段时间,在博客园里看到有位朋友,问如何实现在动态表名。我们都知道,把一个实体类映谢到表里,应该这样写:
[Table(Name="User")]
classUser
{
[Column]
publicintID;
[Column]
publicstringName;
}
很明显,这里的表名是写死的,有些时候,我们可能要根据不同的情况实现不同的表名里加个前缀或者后缀,例如:
tt_User,aa_User,User1、User2。
分析问题
要解决这个问题,首先我们就要明白一个问题,DataContext是如何将实体到表的映射的,事实上,它是例用MappingSource提供的信息来进行映射的。要解决上面的问题,我就是需要重新构一个继承于MappingSource的类。
解决问题
代码如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Data.Linq;
usingSystem.Data.Linq.Mapping;
usingSystem.Diagnostics;
usingSystem.Globalization;
usingSystem.Linq;
usingSystem.Reflection;
usingSystem.Text;
usingSystem.Xml.Schema;
namespaceALinq.Mapping
{
classDynamicMappingSource:MappingSource
{
classDynamicAttributedMetaModel:MetaModel
{
privateMetaModelsource;
privateconststringTypeName="System.Data.Linq.Mapping.AttributedMetaModel";
privateDynamicMappingSourcemappingSource;
internalDynamicAttributedMetaModel(MappingSourcemappingSource,TypecontextType)
{
this.mappingSource=(DynamicMappingSource)mappingSource;
varbf=BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.CreateInstance;
varargs=newobject[]{mappingSource,contextType};
source=typeof(DataContext).Assembly.CreateInstance(TypeName,false,bf,null,
args,CultureInfo.CurrentCulture,null)asMetaModel;
Debug.Assert(source!=null);
}
publicoverrideMetaTableGetTable(TyperowType)
{
if(mappingSource.GetMetaTableName!=null)
{
vartypeName="System.Data.Linq.Mapping.AttributedMetaTable";
varbf=BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.CreateInstance;
varattribute=newTableAttribute{Name=mappingSource.GetMetaTableName(rowType)};
varargs=newobject[]{source,attribute,rowType};
varmetaTable=typeof(DataContext).Assembly.CreateInstance(typeName,false,bf,null,
args,CultureInfo.CurrentCulture,null)asMetaTable;
returnmetaTable;
}
returnsource.GetTable(rowType);
}
publicoverrideMetaFunctionGetFunction(MethodInfomethod)
{
returnsource.GetFunction(method);
}
publicoverrideIEnumerable<MetaTable>GetTables()
{
returnsource.GetTables();
}
publicoverrideIEnumerable<MetaFunction>GetFunctions()
{
returnsource.GetFunctions();
}
publicoverrideMetaTypeGetMetaType(Typetype)
{
returnsource.GetMetaType(type);
}
publicoverrideMappingSourceMappingSource
{
get{returnsource.MappingSource;}
}
publicoverrideTypeContextType
{
get{returnsource.ContextType;}
}
publicoverridestringDatabaseName
{
get{returnsource.DatabaseName;}
}
publicoverrideTypeProviderType
{
get{returnsource.ProviderType;}
}
}
publicFunc<Type,string>GetMetaTableName;
protectedoverrideMetaModelCreateModel(TypedataContextType)
{
if(dataContextType==null)
{
thrownewArgumentNullException("dataContextType");
}
returnnewDynamicAttributedMetaModel(this,dataContextType);
}
}
[Table(Name="User")]
classUser
{
[Column]
publicintID;
[Column]
publicstringName;
}
classProgram
{
staticvoidMain(string[]args)
{
varmappingSource=newDynamicMappingSource();
inti=0;
mappingSource.GetMetaTableName=delegate(Typetype)
{
varatt=type.GetCustomAttributes(typeof(TableAttribute),true).Single()
asTableAttribute;
Debug.Assert(att!=null);
returnatt.Name+i;
};
varconstr=@"DataSource=NOTEBOOKSQLEXPRESS;InitialCatalog=DemoDataContext;IntegratedSecurity=True";
varcontext=newDataContext(constr,mappingSource){Log=Console.Out};
i=1;
context.GetTable<User>().Select(o=>o).ToList();
i=2;
context.GetTable<User>().Select(o=>o).ToList();
}
}
}