C# 子类化数据表

C# 子类化数据表,c#,entity-framework,sql-server-2012,C#,Entity Framework,Sql Server 2012,我使用的是实体框架和一个接受表值参数(TVP)的存储过程。为此,我需要创建一个DataTable,并按如下方式填充它: var i = new DataTable(); i.Columns.Add("Type", typeof(byte)); i.Columns.Add("Code", typeof(int)); i.Rows.Add(0, 0); i.Rows.Add(2, 31); i.Rows.Add(4, 3121); i.Rows.Add(4, 3111); 然后我可以将其作为参数传

我使用的是实体框架和一个接受表值参数(TVP)的存储过程。为此,我需要创建一个
DataTable
,并按如下方式填充它:

var i = new DataTable();
i.Columns.Add("Type", typeof(byte));
i.Columns.Add("Code", typeof(int));
i.Rows.Add(0, 0);
i.Rows.Add(2, 31);
i.Rows.Add(4, 3121);
i.Rows.Add(4, 3111);
然后我可以将其作为参数传递给调用
SqlQuery

var result = ctx.Database.SqlQuery<MyResult>("select * from myStoredProc(@i)",
    new SqlParameter("@i",i) { TypeName = "MyTVP" });
因此,现在我创建和填充表的代码如下:

var i = new MyTVP();
i.Rows.Add(0, 0);
i.Rows.Add(2, 31);
i.Rows.Add(4, 3121);
i.Rows.Add(4, 3111);
但是如果我尝试将其作为参数传递给存储的进程,我会得到一个
ArgumentException

No mapping exists from object type MyTVP to a known managed provider native type.
是否有一种方法可以将数据表子类化为
DataTable
,以便将其传递给存储的进程

我通过让
MyTVP
包装一个
DataTable
来解决这个问题,然后使用一个属性公开
DataTable
,但它有点混乱

堆栈跟踪:

   at System.Data.SqlClient.MetaType.GetMetaTypeFromValue(Type dataType, Object value, Boolean inferLen, Boolean streamAllowed)
   at System.Data.SqlClient.SqlParameter.GetMetaTypeOnly()
   at System.Data.SqlClient.SqlParameter.get_DbType()
   at System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.LogParameter[TResult](DbCommand command, DbCommandInterceptionContext`1 interceptionContext, DbParameter parameter)
   at System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.LogCommand[TResult](DbCommand command, DbCommandInterceptionContext`1 interceptionContext)
   at System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.Executing[TResult](DbCommand command, DbCommandInterceptionContext`1 interceptionContext)
   at System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.ReaderExecuting(DbCommand command, DbCommandInterceptionContext`1 interceptionContext)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__d(IDbCommandInterceptor i, DbCommand t, DbCommandInterceptionContext`1 c)
   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
   at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryInternal[TElement](String commandText, String entitySetName, ExecutionOptions executionOptions, Object[] parameters)
   at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass65`1.<ExecuteStoreQueryReliably>b__64()
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass65`1.<ExecuteStoreQueryReliably>b__63()
   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryReliably[TElement](String commandText, String entitySetName, ExecutionOptions executionOptions, Object[] parameters)
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQuery[TElement](String commandText, ExecutionOptions executionOptions, Object[] parameters)
   at System.Data.Entity.Internal.InternalContext.<>c__DisplayClass14`1.<ExecuteSqlQuery>b__13()
   at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at ConsoleApplication2.Program.Main(String[] args) in c:\Users\matt.burland\Documents\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 72
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
at System.Data.SqlClient.MetaType.GetMetaTypeFromValue(类型数据类型、对象值、布尔推断、布尔流允许)
位于System.Data.SqlClient.SqlParameter.GetMetaTypeOnly()处
在System.Data.SqlClient.SqlParameter.get_DbType()处
位于System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.LogParameter[TResult](DbCommand命令,DbCommandInterceptionContext`1 interceptionContext,DbParameter参数)
位于System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.LogCommand[TResult](DbCommand命令,DbCommandInterceptionContext`1 interceptionContext)
在System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.Executing[TResult](DbCommand命令,DbCommandInterceptionContext`1 interceptionContext)
位于System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter.ReaderExecuting(DbCommand命令,DbCommandInterceptionContext`1 interceptionContext)
在System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.b_ud(IDBComandInterceptor i,DbCommandT,DbCommandInterceptonContext`1c)
在System.Data.Entity.Infrastructure.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget目标,Func`3操作,TInterceptionContext拦截Context,操作`3执行,操作`3执行)
位于System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand命令,DbCommandInterceptionContext interceptionContext)
位于System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior)
位于System.Data.Common.DbCommand.ExecuteReader(CommandBehavior)
位于System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryInternal[TElement](String commandText,String entitySetName,ExecutionOptions ExecutionOptions,Object[]参数)
在System.Data.Entity.Core.Objects.ObjectContext.c__DisplayClass65`1.b__64()中
在System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 Func,IDBEcutionStrategy executionStrategy,Boolean startLocalTransaction,Boolean releaseConnectionOnSuccess)
位于System.Data.Entity.Core.Objects.ObjectContext.c__uDisplayClass65`1.b__63()
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1操作)中
位于System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryReliably[TElement](String commandText,String entitySetName,ExecutionOptions ExecutionOptions,Object[]参数)
位于System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQuery[TElement](String commandText,ExecutionOptions ExecutionOptions,Object[]参数)
在System.Data.Entity.Internal.InternalContext.c__DisplayClass14`1.b__13()中
位于System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
位于System.Collections.Generic.List`1..ctor(IEnumerable`1集合)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
在c:\Users\matt.burland\Documents\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\Program.Main(字符串[]args)中的ConsoleApplication2.Program.Main处:第72行
位于System.AppDomain.\u nExecuteAssembly(RuntimeAssembly程序集,字符串[]args)
位于System.AppDomain.ExecuteAssembly(字符串汇编文件、证据汇编安全性、字符串[]args)
在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()上
位于System.Threading.ThreadHelper.ThreadStart\u上下文(对象状态)
位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext、ContextCallback回调、对象状态、布尔值preserveSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔保存SyncCTX)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
位于System.Threading.ThreadHelper.ThreadStart()处

另一个选项是,不创建新类型,而是创建一个DataTable工厂,创建具有正确列的datatables。

尝试将参数更改为:

new SqlParameter("@i", i) { TypeName = "MyTVP", SqlDbType = SqlDbType.Structured }

您可以解决这个问题:创建一个返回
数据表的静态方法,或者一个类似MyTVPBuilder.Create().Add(0,0).Add(2,31).ToDataTable()的流畅接口。您能给我完整的堆栈跟踪吗,这样我就可以看到错误发生的地方了?哈。这似乎解决了问题。谢谢
new SqlParameter("@i", i) { TypeName = "MyTVP", SqlDbType = SqlDbType.Structured }