عمل نکردن event ها

سوال شده توسط: علی شاکری

تاریخ ثبت: ۱۴۰۲/۰۱/۰۳

بازدید: 419

پاسخ: 24

تگ: Asp.net Core


سلام استاد

نمیدونم چرا event ها پابلیش نمیشن

میخام یک notification برای کاربر اضافه کنم و یک sms هم بدم  نمیشه 

دیباگم کردم ولی انگار event handler اجرا نمیشه

پاسخ ها
user

محمد اشرافی

سلام وقت بخیر ، Event رو پابلیش کردین ؟ توی این عکس ها که این اتفاق نیوفتاده ( قبلا توی متد SaveChangeAsync این کار رو انجام داده بودیم )

user

علی شاکری

بله استاد داخل همون متد save هست

با همون custom publish که خودتون درست کردید

user

علی شاکری

الان گیر میده به save کردن نوتیفیکیشن یوزر

میگه هنوز عملیات قبلی تموم نشده

user

محمد اشرافی

خطایی که میده رو بزارید ببینم چیه

user

علی شاکری

سلام استاد

هیچ اروری نمیده

طبق این عکس بعد از بریک پوینت اول به هیچ کدوم دیگه نمیرسه و پیام موفقیت میده

user

علی شاکری

استاد این ارور را با serilog گرفتم

An exception occurred while iterating over the results of a query for context type '"EShop.Infrastructure.Persistent.Ef.ShopDbContext"'."

""System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.

  at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()

  at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()"
user

علی شاکری

System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.

  at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()

  at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()

  at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)

  at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)

  at EShop.Infrastructure._Utilities.BaseRepository`1.GetTracking(Int64 id) in E:\Projects\EShop\EShop.Infrastructure\_Utilities\BaseRepository.cs:line 23

  at EShop.Application.Orders._EventHandlers.SendSmsOrderSendedEventHandler.Handle(OrderSended notification, CancellationToken cancellationToken) in E:\Projects\EShop\EShop.Application\Orders\_EventHandlers\SendSmsOrderSendedEventHandler.cs:line 27
user

محمد اشرافی

سلام مجدد ، مشکل از GetTracking اتونه ، به صورت معمولی دریافت اش کنید ببینم مشکل حل میشه 

و مورد بعدی اینکه Notification هارو بهتره  توی  یه Aggregate  با User قرار ندین چون تعداد Notification ها میره بالا و برای هر بار گرفتن User باید کل Notification هارو هم از دیتابیس دریافت کنید

user

علی شاکری

سلام استاد

مشکل حل نشد

من اومدم کلا یه aggregate برای نوتیفیکیشن درست کردم و دوباره مثل عکس زیر تغییر دادم ولی مشکل داره

فک کنم اصلا نمیشه در eventhandler با روش mediatR کلا کوئری بزنیم و اطلاعات واکشی کنیم و یا save کنیم

چون عملیات save قبلی تموم نشده و ما اومدیم پابلیش رو در متد save قرار دادیم

user

علی شاکری

اینم خطاش

{"@t":"2023-03-29T02:50:07.3537813Z","@mt":"An exception occurred while iterating over the results of a query for context type '{contextType}'.{newline}{error}","@l":"Error","@x":"System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.\r\n   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()","contextType":"EShop.Infrastructure.Persistent.Ef.ShopDbContext","newline":"\r\n","error":"System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.\r\n   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()","EventId":{"Id":10100,"Name":"Microsoft.EntityFrameworkCore.Query.QueryIterationFailed"},"SourceContext":"Microsoft.EntityFrameworkCore.Query","ActionId":"e7a0ee82-c8ba-4712-b756-f235b47c8043","ActionName":"/Admin/Orders/Show","RequestId":"0HMPG006EDKEE:00000115","RequestPath":"/Admin/Orders/Show/3","ConnectionId":"0HMPG006EDKEE"}
user

محمد اشرافی

طبیعتا نباید مشکی پیش بیاد چون هر چند بار بخوایم میتونیم SaveChange  رو فراخوانی کنیم ولی این وسط مشکلی که پیش میاد اینه که میوفته توی یه حلقه و هی Event رو پابلیش میکنه  ( چون توی EventHandler هم دوباره صداش می زنیم ، کاری که باید انجام بدین اینه که بعد از اینکه Event هارو پابلیش کردین ، لیست Event هارو پاک کنید ) 

توی Aggregate root یه متد به اسم ClearEvents بسازید و صداش بزنید 

user

محمد اشرافی

یعنی به این شکل بشه :

 private async Task PublishEvents(List<AggregateRoot> modifiedEntities)
    {
        foreach (var entity in modifiedEntities)
        {
            var events = entity.DomainEvents.ToList();
            entity.ClearnEvents();
            foreach (var domainEvent in events)
            {
                await _publisher.Publish(domainEvent,PublishStrategy.ParallelNoWait);
            }
        }
    }
user

علی شاکری

سلام استاد

من اومدم این entity.DomainEvents.Clear(); رو بجای clearevents اضافه کردم ولی بازم کار نمیکنه

user

علی شاکری

private async Task PublishEvents(List<AggregateRoot> modifiedEntities)
    {
        foreach (var entity in modifiedEntities)
        {
            var events = entity.DomainEvents.ToList();
            entity.DomainEvents.Clear();
            foreach (var domainEvent in events)
            {
                await _publisher.Publish(domainEvent, PublishStrategy.ParallelNoWait);
            }
        }
    }
user

علی شاکری

[22:25:47 ERR] An exception occurred while iterating over the results of a query for context type 'EShop.Infrastructure.Persistent.Ef.ShopDbContext'.
System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
user

محمد اشرافی

SaveChange توی Event Handler رو بردارین مشکل حل میشه ؟

user

علی شاکری

سلام استاد

بازم این ارور رو میده

InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
user

علی شاکری

استاد من اومدم در infrastructurebootstrapper کد رو به این تغییر دادم

services.AddDbContext<ShopDbContext>(option =>
            {
                option.UseSqlServer(connectionString);
            }, ServiceLifetime.Transient);

سرویس لایف تایم رو به transient تغییر دادم و در eventhandler هم save را پاک نکردم و الان درست شد و کار میکنه

 

به نظرتون این تغییر در servicelifetime مشکل ساز نمیشه؟

 

user

محمد اشرافی

فکر نمیکنم مشکل خاصی پیش ، به صورت پیشفرض خود اش Scope ه ، ولی اگر Singleton اش میکردین به مشکل میخورد

user

علی شاکری

خب استاد الان من باید تو همه پروژه های بزرگ این تغییر رو انجام بدم؟

الان من از rich مدل استفاده کردم.به نظرم روش خوبیه فقط یکم توی کوئری گرفتن با dapper سختم بود.مثلا برای نوشتن کوئری صفحه بندی productshop هنوز کامل متوجه نشدم و از chatgpt کمک گرفتم خخخ

الان برای نوشتن کوئری های پیچیده ابزار خاصی هست یا باید بشینیم و بنویسیم؟

user

محمد اشرافی

نه نیازی نیست من همیشه همینطور استفاده میکردم نمیدونم چرا براش شما این مشکل پیش اومده ولی ممکنه توی نسخه جدید اینطور شده باشه

برای Query هم توی پروژه آخری بهتون گفتم میتونید از QueryContext استفاده کنید که خیلی Query گرفتن راحت میشه

user

علی شاکری

منتظرم پروژه digilearn کامل بشه بعد ببینم

در کل میخاستم بدونم اگه کلا با دپر بخام بزنم چطوری میشه؟ابزار خاصی برای نوشتن کوئری های پیچیده نیست؟

user

محمد اشرافی

نه دیگه اگر بخواین Raw Sql استفاده کنید باید کد های SQL استفاده کنید

user

علی شاکری

ممنون استاد

برای ثبت پاسخ باید خود شوید

محبوب ترین مقالات