web-dev-qa-db-ja.com

誰かがDapperORMを使用して一括更新を行うのを手伝ってもらえますか?

テーブルemployeeがあり、それらの場所を新しい場所に更新する必要があるため、一括更新が必要です。 DapperO.R.Mを使用してそうするのを手伝ってください。

私の主キーはEmployee-id

以下に、一度に1つのレコードで更新されるサンプルコードを示します。

// Employees is list of class class Employee
SqlConnection connection = new SqlConnection(connectionstring);
connection.open();

foreach (Employee employee in Employees)
{
    string query = @"UPDATE [dbo].[Employee]    
                     SET Name = @Name, Age = @Age, Sex = @Sex, 
                         Location = @Location  
                     WHERE Id = @Id";

    connection.QueryAsync<bool>(query, new { @Id = employee.Id, @Name = employee.Name, 
                                             @Sex = employee.sex, @Age = employee.age, 
                                             @Location = employee.location})).SingleOrDefault();
}   
10
chaaru

Dapperは、リストからの挿入/更新をサポートしています。

internal class Employee
{
    public int Id { get; set; }
    public int Age { get; set; }
    public string Name { get; set; }
}

[TestFixture]
public class DapperTests
{
    private IDbConnection _connection;

    [SetUp]
    public void SetUp()
    {
        _connection = new SqlConnection(@"Data Source=.\sqlexpress; Integrated Security=true; Initial Catalog=mydb");
        _connection.Open();

        _connection.Execute("create table employees(Id int, Name varchar(100), Age int)");
        _connection.Execute("insert into employees(Id, Name) values(1, 'xxx'), (2, 'yyy')");
    }

    [TearDown]
    public void TearDown()
    {
        _connection.Execute("drop table employees");
        _connection.Close();
    }

    [Test]
    public void BulkUpdateFromAListTest()
    {
        _connection.Execute(@"update employees set Name = @Name where Id = @Id",
            new List<Employee> 
            {
                new Employee{Age = 1, Name = "foo", Id = 1},
                new Employee{Age = 2, Name = "bar", Id = 2}
            });

        var result = _connection.Query<Employee>("select * from employees").ToList();

        Assert.That(result.Count, Is.EqualTo(2));
        Assert.That(result.FirstOrDefault(x => x.Id == 1).Name == "foo");
        Assert.That(result.FirstOrDefault(x => x.Id == 2).Name == "bar");

    }
}

Dapperの問題は、各コマンドを個別に実行することです。そのため、多数ある場合は、パフォーマンスの問題が発生します。

別のアプローチは、一時テーブルを作成してから、結合で更新することです。このために、あなたはこのようなことをすることができます:

[TestFixture]
public class BatchRunnerTests
{
    private readonly IDbConnection _dbConnection;

    public BatchRunnerTests()
    {
        _dbConnection = new SqlConnection(@"Data Source=.\sqlexpress; Integrated Security=true; Initial Catalog=Bktb4_CaseMgr_Db"); ;
        _dbConnection.Open();
    }

    [Test]
    public void TestBatchRunner()
    {
        var records = new List<Employee>
        {
            new Employee {Age = 1, Name = "foo", Id = 1},
            new Employee {Age = 2, Name = "bar", Id = 2}
        };

        var tablwToUpdateFrom = BuildTable(records);

        _dbConnection.Execute("update a set Name = b.Name from employees a join " + tablwToUpdateFrom + " b on a.Id = b.Id");
    }

    public string BuildTable(List<Employee> data)
    {
        var tableName = "#" + Guid.NewGuid();

        _dbConnection.Execute("create table [" + tableName + "] ( Id int null, Name varchar(50) null)");

        var batchRunner = new SqlBatchRunner(_dbConnection);

        data.ToList().ForEach(x =>
            batchRunner.RecordingConnection.Execute(@"insert into [" + tableName + "] values(@Id, @Name)", x));

        batchRunner.Run();
        return tableName;
    }
}

ここで使っている library は友達が書いたものです。挿入ステートメントのグループを生成し、それらを一度に実行するだけです。

12
Void Ray