【问题标题】:EF Dynamic type - The SqlParameter is already contained by another SqlParameterCollectionEF 动态类型 - SqlParameter 已被另一个 SqlParameterCollection 包含
【发布时间】:2019-04-10 17:10:16
【问题描述】:

我有一个存储过程会给出一个动态的结果集

(Eg1. storedProcedureNameXX 4 - sql server result  may be 5 columns)
(Eg2. storedProcedureNameXX 1 - sql server result  may be 3 columns)

假设我在类型生成器中添加了动态列:

TypeBuilder builder = CreateTypeBuilder("MyDynamicAssembly", "MyModule", "MyType")<br>

//Todo:get the dynamic column names

CreateAutoImplementedProperty(builder, "column1", typeof(string));
CreateAutoImplementedProperty(builder, "column2", typeof(string));
CreateAutoImplementedProperty(builder, "column3", typeof(string));

Type resultType = builder.CreateType();
var parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("parm1", 1));

var  **p1** = entity.Database
    .SqlQuery(resultType, "exec storedProcedureNameXX @parm1", parameters.ToArray());

P1 变量错误:

"SqlParameter 已经被另一个包含 SqlParameterCollection" 无法放置 ToList()

//添加使用的方法
私有静态 TypeBuilder createTypeBuilder(字符串组件名称,字符串模块名称,字符串类型名称) { TypeBuilder typeBuilder = AppDomain .CurrentDomain .DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run) .DefineDynamicModule(模块名称) .DefineType(typeName, TypeAttributes.Public); typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); 返回类型生成器; }
私有静态无效 createAutoImplementedProperty( TypeBuilder 构建器,字符串 propertyName,Type propertyType) { 常量字符串 PrivateFieldPrefix = "m_"; 常量字符串 GetterPrefix = "get_"; const string SetterPrefix = "set_";

        // Generate the field.
        FieldBuilder fieldBuilder = builder.DefineField(
            string.Concat(PrivateFieldPrefix, propertyName),
                          propertyType, FieldAttributes.Private);

        // Generate the property
        PropertyBuilder propertyBuilder = builder.DefineProperty(
            propertyName, System.Reflection.PropertyAttributes.HasDefault, propertyType, null);

        // Property getter and setter attributes.
        MethodAttributes propertyMethodAttributes =
            MethodAttributes.Public | MethodAttributes.SpecialName |
            MethodAttributes.HideBySig;

        // Define the getter method.
        MethodBuilder getterMethod = builder.DefineMethod(
            string.Concat(GetterPrefix, propertyName),
            propertyMethodAttributes, propertyType, Type.EmptyTypes);

        // Emit the IL code.
        // ldarg.0
        // ldfld,_field
        // ret
        ILGenerator getterILCode = getterMethod.GetILGenerator();
        getterILCode.Emit(OpCodes.Ldarg_0);
        getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
        getterILCode.Emit(OpCodes.Ret);

        // Define the setter method.
        MethodBuilder setterMethod = builder.DefineMethod(
            string.Concat(SetterPrefix, propertyName),
            propertyMethodAttributes, null, new Type[] { propertyType });

        // Emit the IL code.
        // ldarg.0
        // ldarg.1
        // stfld,_field
        // ret
        ILGenerator setterILCode = setterMethod.GetILGenerator();
        setterILCode.Emit(OpCodes.Ldarg_0);
        setterILCode.Emit(OpCodes.Ldarg_1);
        setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
        setterILCode.Emit(OpCodes.Ret);

        propertyBuilder.SetGetMethod(getterMethod);
        propertyBuilder.SetSetMethod(setterMethod);
    }    

【问题讨论】:

  • 如果您尝试枚举p1 两次,则会抛出该错误。
  • @davidg:这是一次执行..
  • 即使只是将鼠标悬停在p1 变量上,也可能会导致数据具体化,这意味着您的代码稍后会尝试再次执行此操作。

标签: c# entity-framework stored-procedures


【解决方案1】:

听起来像是deferred execution 的影响。通常简单的ToList() 调用应该可以工作:

var p1 = entity.Database.SqlQuery(resultType, "exec storedProcedureNameXX @parm1", parameters.ToArray()).ToList();

如果上面的ToList() 仍然不起作用,请尝试克隆现有的SqlParameter 实例并像以下示例一样使用它:

var p1 = entity.Database.SqlQuery(resultType, "exec storedProcedureNameXX @parm1", 
                parameters.Select(x => ((ICloneable)x).Clone()).ToArray()).ToList();

或者Database.SqlQuery&lt;T&gt;:

var p1 = entity.Database.SqlQuery<resultType>("exec storedProcedureNameXX @parm1", 
                    parameters.Select(x => ((ICloneable)x).Clone()).ToArray()).ToList();

参考:SqlParameter.ICloneable.Clone Method

相关问题:Database.SqlQuery gives the The SqlParameter is already contained by another SqlParameterCollection

【讨论】:

  • 我已经尝试过了
    var p1 = entity.Database.SqlQuery(resultType, "exec storedProcedureNameXX @parm1", parameters.ToArray()).ToList();
    var p1 = entity.Database.SqlQuery(resultType, "exec storedProcedureNameXX @parm1", parameters.Select(x => ((ICloneable)x).Clone()).ToArray()).ToList();
    tolist()没有出现
  • 我不能用作 Database.SqlQuery:因为结果类型是动态列/类。
猜你喜欢
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 2011-12-11
  • 2011-09-11
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多