我为Linq To Sql(L2S)创建了一个更新操作,其工作原理如下:
var rowsaffected = db.Tables.Where(...).Join...Group..
.Update(x => new Table { Column = x.Something });
问题是L2S不允许您在查询中创建实体(上面的行在运行时导致异常)。
为了解决这个问题,我创建了一个非实体类:
class TableUpdate : Table { }
并在更新
中使用它.Update(x => new TableUpdate { Column = x.Something });
工作正常。
现在的问题是,如果在运行时动态创建TableUpdate
类并在将其发送到L2S sql生成器之前将其替换为表达式树是个好主意吗?
该类永远不会被实例化,因此不需要代码,只需元数据。
我认为性能不是问题(与实际的数据库更新相比),还有其他想法吗?
更新
解决这个问题:
private static readonly Dictionary<Type, Type> _noEntityClasses = new Dictionary<Type, Type>(1);
private static ModuleBuilder _module;
private static Type CreateNoEntityClass(Type entityClass) {
lock (_noEntityClasses) {
Type noentityClass;
if (!_noEntityClasses.TryGetValue(entityClass, out noentityClass)) {
if (_module == null) {
var assemblyName = new AssemblyName("LinqToSqlGenerated");
var assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
_module = assemblyBuilder.DefineDynamicModule("NonEntity");
}
var typeBuilder = _module.DefineType(entityClass.Name + "NoEntity", TypeAttributes.Class | TypeAttributes.NotPublic, entityClass);
noentityClass = typeBuilder.CreateType();
_noEntityClasses.Add(entityClass, noentityClass);
}
return noentityClass;
}
}
private static IQueryable<T> RemoveEntity<T>(IQueryable<T> source, DataContext context) {
var mapping = context.Mapping.MappingSource.GetModel(context.GetType());
var noEntityExpression = source.Expression.Visit<MemberInitExpression>(expression => {
if (!mapping.GetMetaType(expression.Type).IsEntity)
return expression;
return Expression.MemberInit(Expression.New(CreateNoEntityClass(expression.Type)), expression.Bindings);
});
return source.Provider.CreateQuery<T>(noEntityExpression);
}
答案 0 :(得分:1)
使用RunSharp,您可以轻松创建一个从现有类扩展的新类。
您可以创建一个创建这些包装类的类,并跟踪它已经构造了类的类型。可能是Dictionary<Type, Type>
,将原始类型链接到动态创建的包装类型。
此类中的静态函数只是初始化此包装类型。
public static object ExtendedClassInstance<T>()
{
Type type = typeof( T );
if ( !_wrappedTypes.Contains( type ) )
{
// Use RunSharp to create the type.
}
return Activator.CreateInstance( _wrappedTypes[ type ] );
}
答案 1 :(得分:0)
我使用的一种技术是使用T4 Template生成类似的类。 Oleg博客的链接有一些有用的教程。
从问题描述中,它听起来不像你需要运行时生成,只是编译时。如果你真的需要运行时,T4将无济于事。