我使用Entity Framework获得显着降低的性能的原因是什么?以下代码的两个版本都实现了完全相同的目标。
Excel文档包含1700条正在插入SQL Azure数据库的记录。
使用实体框架执行时间:4:55
foreach (IXLRow row in wb.Worksheet(1).RowsUsed())
{
dbContext.InsertQuestion(row.Cell("B").Value.ToString().Trim(), row.Cell("A").Value.ToString().Trim(), row.Cell("C").Value.ToString().Trim(), row.Cell("D").Value.ToString().Trim(), null);
}
非实体框架执行时间:1:54
foreach (IXLRow row in wb.Worksheet(1).RowsUsed())
{
using (SqlCommand cmd = new SqlCommand("InsertQuestion", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@CategoryName", row.Cell("B").Value.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("@TypeName", row.Cell("A").Value.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("@Text", row.Cell("C").Value.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("@Answer", row.Cell("D").Value.ToString().Trim()));
cmd.ExecuteNonQuery();
}
}
答案 0 :(得分:0)
首先,在数据库上创建一个数据类型(比如数据库有VARCHAR和INT类型,你可以创建自己的TYPE。)
CREATE TYPE SurveyAnswerType AS TABLE
(
CategoryName VARCHAR(255),
TypeName VARCHAR(255),
[Text] VARCHAR(255),
Answer VARCHAR(255)
)
GO
其次,使用新类型作为存储过程的参数
CREATE PROCEDURE InsertSurveyAnswers
@Answers SurveyAnswerType READONLY
AS
INSERT INTO Answers
(CategoryName, TypeName, [Text], Answer)
SELECT CategoryName, TypeName, [Text], Answer
FROM @Answers
GO
第三,通过加载一个看起来像你的新类型的表来从C#代码调用存储过程:
DataTable tAnswers = new DataTable();
tAnswers.Columns.Add("CategoryName", typeof(String));
tAnswers.Columns.Add("TypeName", typeof(String));
tAnswers.Columns.Add("Text", typeof(String));
tAnswers.Columns.Add("Answer", typeof(String));
var rows = wb.Worksheet(1).RowsUsed();
var totalRows = rows.Count();
int index = 0;
int bufferSize;
using (SqlCommand cmd = new SqlCommand("InsertAnswers", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@SurveyAnswerType",
SqlDbType.Structured));
while(index < totalRows)
{
int bufferSize = Math.Min(200, totalRows - index);
foreach (index = index; index < bufferSize; index++)
{
var newRow = tAnswerstAnswers.NewRow();
newRow[0] = rows[index].Cell("A").Value.ToString().Trim();
newRow[1] = row[index].Cell("B").Value.ToString().Trim();
newRow[2] = row[index].Cell("C").Value.ToString().Trim();
newRow[3] = row[index].Cell("D").Value.ToString().Trim();
tAnswerstAnswers.AddRow(newRow);
}
cmd.Parameters["@SurveyAnswerType"].Value = tAnswers;
cmd.ExecuteNonQuery();
}
}
注意事项:
SqlParameter使用SqlDbType.Structured。
连接仅打开和关闭/销毁一次,而不是一次打开 每一行。
您应该使用缓冲区大小来查看最佳大小。
您必须提出自己的实体框架版本 这个 - 但我怀疑你的每次通话都有开销 将这种模式最小化。