عمل نکردن event ها
سلام استاد
نمیدونم چرا event ها پابلیش نمیشن





میخام یک notification برای کاربر اضافه کنم و یک sms هم بدم نمیشه
دیباگم کردم ولی انگار event handler اجرا نمیشه
پاسخ ها

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

علی شاکری
بله استاد داخل همون متد save هست
با همون custom publish که خودتون درست کردید

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

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

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


علی شاکری
استاد این ارور را با 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()"

علی شاکری
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

محمد اشرافی
سلام مجدد ، مشکل از GetTracking اتونه ، به صورت معمولی دریافت اش کنید ببینم مشکل حل میشه
و مورد بعدی اینکه Notification هارو بهتره توی یه Aggregate با User قرار ندین چون تعداد Notification ها میره بالا و برای هر بار گرفتن User باید کل Notification هارو هم از دیتابیس دریافت کنید

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

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

علی شاکری
اینم خطاش
{"@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"}

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

محمد اشرافی
یعنی به این شکل بشه :
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);
}
}
}

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

علی شاکری
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);
}
}
}

علی شاکری
[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()

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

علی شاکری
سلام استاد
بازم این ارور رو میده
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.

علی شاکری
استاد من اومدم در infrastructurebootstrapper کد رو به این تغییر دادم
services.AddDbContext<ShopDbContext>(option =>
{
option.UseSqlServer(connectionString);
}, ServiceLifetime.Transient);
سرویس لایف تایم رو به transient تغییر دادم و در eventhandler هم save را پاک نکردم و الان درست شد و کار میکنه
به نظرتون این تغییر در servicelifetime مشکل ساز نمیشه؟

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

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

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

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

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

علی شاکری
ممنون استاد
محبوب ترین مقالات



