我在SQL Server中创建了一个用户定义的表类型:
CREATE TYPE dbo.TestType AS TABLE
(
ColumnA int,
ColumnB nvarchar(500)
)
我正在使用存储过程将记录插入数据库:
create procedure [dbo].[sp_Test_CustomType]
@testing TestType READONLY
as
insert into [dbo].[myTable]
select ColumnA, ColumnB
from @testing
我想使用EF来执行此存储过程,但问题是:如何将用户定义的表传递给存储过程?
我尝试将存储过程添加到模型中,但我无法在更新的上下文中找到所需的存储过程。
我要做的是对表执行批量插入,这是我目前使用的方法:
List<items> itemToInsertToDB = //fetchItems;
foreach(items i in itemToInsertToDB)
{
context.sp_InsertToTable(i.ColumnA, i.ColumnB)
}
目前,我用的是 foreach
循环遍历列表以将项插入到DB,但如果列表中有很多项,那么就会出现性能问题,因此,我正在考虑将列表传递给存储过程并在内部插入。
那么如何解决这个问题呢?或者有更好的方法吗?
假设您要发送一个包含一列GUID的表。
首先,我们需要使用创建结构 SqlMetaData 表示表(列)的模式。
var tableSchema = new List<SqlMetaData>(1)
{
new SqlMetaData("Id", SqlDbType.UniqueIdentifier)
}.ToArray();
接下来,您将创建与使用的架构匹配的记录列表 的SqlDataRecord。
var tableRow = new SqlDataRecord(tableSchema);
tableRow.SetGuid(0, Guid.NewGuid());
var table = new List<SqlDataRecord>(1)
{
tableRow
};
然后创建 的SqlParameter:
var parameter = new SqlParameter();
parameter.SqlDbType = SqlDbType.Structured;
parameter.ParameterName = "@UserIds";
parameter.Value = table;
var parameters = new SqlParameter[1]
{
parameter
};
然后只需使用。调用存储过程 Database.SqlQuery。
IEnumerable<ReturnType> result;
using (var myContext = new DbContext())
{
result = myContext.Database.SqlQuery<User>("GetUsers", parameters)
.ToList(); // calls the stored procedure
// ToListAsync(); // Async
{
在SQL Server中,创建用户定义的表类型(我用TTV,表类型值后缀):
CREATE TYPE [dbo].[UniqueidentifiersTTV] AS TABLE(
[Id] [uniqueidentifier] NOT NULL
)
GO
然后将类型指定为参数(不要忘记,表类型值必须是只读的!):
CREATE PROCEDURE [dbo].[GetUsers] (
@UserIds [UniqueidentifiersTTV] READONLY
) AS
BEGIN
SET NOCOUNT ON
SELECT u.* -- Just an example :P
FROM [dbo].[Users] u
INNER JOIN @UserIds ids On u.Id = ids.Id
END
我建议您不要使用存储过程来插入批量数据,而只是依赖于Entity Framework插入机制。
List<items> itemToInsertToDB = //fetchItems;
foreach(items i in itemToInsertToDB)
{
TestType t = new TestType() { ColumnA = i.ColumnA, ColumnB = i.ColumnB };
context.TestTypes.Add(t);
}
context.SaveChanges();
实体框架将巧妙地在单个事务中执行那些插入,并且(通常)在单个查询执行中执行,这几乎等于执行存储过程。这是更好的,而不是仅仅依靠存储过程来插入大量数据。