1. ホーム
  2. c#

[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。

2022-02-11 19:14:25

質問

現在、このようなエラーが発生しています。

System.Data.SqlClient.SqlException: セッションで他のスレッドが実行されているため、新しいトランザクションは許可されません。

このコードを実行している間

public class ProductManager : IProductManager
{
    #region Declare Models
    private RivWorks.Model.Negotiation.RIV_Entities _dbRiv = RivWorks.Model.Stores.RivEntities(AppSettings.RivWorkEntities_connString);
    private RivWorks.Model.NegotiationAutos.RivFeedsEntities _dbFeed = RivWorks.Model.Stores.FeedEntities(AppSettings.FeedAutosEntities_connString);
    #endregion

    public IProduct GetProductById(Guid productId)
    {
        // Do a quick sync of the feeds...
        SyncFeeds();
        ...
        // get a product...
        ...
        return product;
    }

    private void SyncFeeds()
    {
        bool found = false;
        string feedSource = "AUTO";
        switch (feedSource) // companyFeedDetail.FeedSourceTable.ToUpper())
        {
            case "AUTO":
                var clientList = from a in _dbFeed.Client.Include("Auto") select a;
                foreach (RivWorks.Model.NegotiationAutos.Client client in clientList)
                {
                    var companyFeedDetailList = from a in _dbRiv.AutoNegotiationDetails where a.ClientID == client.ClientID select a;
                    foreach (RivWorks.Model.Negotiation.AutoNegotiationDetails companyFeedDetail in companyFeedDetailList)
                    {
                        if (companyFeedDetail.FeedSourceTable.ToUpper() == "AUTO")
                        {
                            var company = (from a in _dbRiv.Company.Include("Product") where a.CompanyId == companyFeedDetail.CompanyId select a).First();
                            foreach (RivWorks.Model.NegotiationAutos.Auto sourceProduct in client.Auto)
                            {
                                foreach (RivWorks.Model.Negotiation.Product targetProduct in company.Product)
                                {
                                    if (targetProduct.alternateProductID == sourceProduct.AutoID)
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found)
                                {
                                    var newProduct = new RivWorks.Model.Negotiation.Product();
                                    newProduct.alternateProductID = sourceProduct.AutoID;
                                    newProduct.isFromFeed = true;
                                    newProduct.isDeleted = false;
                                    newProduct.SKU = sourceProduct.StockNumber;
                                    company.Product.Add(newProduct);
                                }
                            }
                            _dbRiv.SaveChanges();  // ### THIS BREAKS ### //
                        }
                    }
                }
                break;
        }
    }
}

モデル #1 - このモデルは、私たちのDevサーバー上のデータベースに格納されています。 モデル#1 http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.png

モデル#2 - このモデルは、当社のProd Server上のデータベースに格納され、自動フィードによって毎日更新されます。 オルトテキスト http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png

注 - Model #1 の赤丸で囲った項目は、Model #2 に "map"するために使用するフィールドです。 モデル#2の赤い丸は無視してください:これは私が持っていた別の質問で、現在は回答済みです。

注:クライアントの在庫がなくなった場合、DB1からソフト的に削除できるように、isDeletedチェックを入れる必要があります。

私がこの特定のコードでやりたいことは、DB1の会社とDB2のクライアントを接続し、DB2から商品リストを取得し、DB1にまだなければそれをINSERTすることです。 初回は、インベントリーを完全に取得する必要があります。 その後、このコードを実行するたびに、一晩中新しい在庫がフィードで入ってこない限り、何も起こらないはずです。

<ブロッククオート

そこで大きな疑問なのですが、トランザクションエラーが発生した場合、どのように解決すればよいのでしょうか? ループを通過するたびにコンテキストを削除して再作成する必要があるのでしょうか?

どのように解決するのですか?

髪を引っ張った末に、私は foreach ループが原因でした。 必要なのは、EFを呼び出しても、それを IList<T> をループさせ、そのターゲット型の IList<T> .

IList<Client> clientList = from a in _dbFeed.Client.Include("Auto") select a;
foreach (RivWorks.Model.NegotiationAutos.Client client in clientList)
{
   var companyFeedDetailList = from a in _dbRiv.AutoNegotiationDetails where a.ClientID == client.ClientID select a;
    // ...
}