5

我有一个带有 .NET 4 和数据层实体框架的 Windows 窗体应用程序我需要一种带有事务的方法,但是进行简单的测试我无法使其工作

在 BLL 中:

public int Insert(List<Estrutura> lista)
{
    using (TransactionScope scope = new TransactionScope())
    {
            id = this._dal.Insert(lista);
    }
}

在 DAL 中:

public int Insert(List<Estrutura> lista)
{
   using (Entities ctx = new Entities (ConnectionType.Custom))
   {
     ctx.AddToEstrutura(lista);
     ctx.SaveChanges(); //<---exception is thrown here
   }
}

“底层提供商在 Open 上失败。”

有人有想法么?

问题已解决 - 我的解决方案

我通过一些更改解决了我的问题。在我的一个 DAL 中,我使用批量插入和其他实体。问题事务是由于大部分事务(事务 sql)不理解事务范围而发生的,所以我在 DAL 中分离了实体,并在运行一些琐碎的过程中使用了 sql 事务。执行标量();

我相信这不是最优雅的方式,但解决了我的问题交易。

这是我的 DAL 的代码

   using (SqlConnection sourceConnection = new SqlConnection(Utils.ConnectionString()))
   {
        sourceConnection.Open();
        using (SqlTransaction transaction = sourceConnection.BeginTransaction())
        {
            StringBuilder query = new StringBuilder();
            query.Append("INSERT INTO...");
            SqlCommand command = new SqlCommand(query.ToString(), sourceConnection, transaction);
            using (SqlBulkCopy bulk = new SqlBulkCopy(sourceConnection, SqlBulkCopyOptions.KeepNulls, transaction))
            {                           
                bulk.BulkCopyTimeout = int.MaxValue;
                bulk.DestinationTableName = "TABLE_NAME";
                bulk.WriteToServer(myDataTable);

                StringBuilder updateQuery = new StringBuilder();
                //another simple insert or update can be performed here
                updateQuery.Append("UPDATE... ");
                command.CommandText = updateQuery.ToString();
                command.Parameters.Clear();
                command.Parameters.AddWithValue("@SOME_PARAM", DateTime.Now);
                command.ExecuteNonQuery();
                transaction.Commit();
            }
        }
    }

谢谢您的帮助

4

2 回答 2

1

根据全能谷歌的说法,EF 似乎会在每次调用数据库时打开/关闭连接。既然这样做了,它将把事务视为使用多个连接(使用分布式事务)。解决这个问题的方法是在使用时手动打开和关闭连接。

这是有关分布式事务问题的信息。

以下是手动打开和关闭连接的方法。

一个小代码示例:

public int Insert(List<Estrutura> lista)
{
    using (TransactionScope scope = new TransactionScope())
    {
        using (Entities ctx = new Entities (ConnectionType.Custom))
        {
            ctx.Connection.Open()

            id = this._dal.Insert(ctx, lista);
        }
    }
}

public int Insert(Entities ctx, List<Estrutura> lista)
{
     ctx.AddToEstrutura(lista);
     ctx.SaveChanges();
}
于 2012-05-22T13:43:18.303 回答
-1

与其使用 TransactionScope,不如在使用实体框架时使用 UnitOfWork 模式。请参考: 工作单元模式

并且;

工作单元和持久性无知

于 2012-05-22T13:41:37.840 回答