ورود

View Full Version : مشکل الگوی واحد کار



micro_bhk
سه شنبه 29 دی 1394, 11:13 صبح
با عرض سلام و خسته نباشید خدمت دوستان
در مقاله ای که آقای نصیری در :
http://www.dotnettips.info/post/842/ef-code-first-12

در رابطه با الگوی واحد کار ایجاد کرده بودند چند سوال در این رابطه داشتم:


1 - با توجه به مشترک بودن نمونه DbContext در سراسر یک Request , اگر در آن Request چند Transaction وجود داشته باشد , متد SaveChanges کجا صدا زده می شود , کدام Transaction اول به پایان میر سد و کدام دیرتر ؟

2 - اگر شما از Multi Thread استفاده کرده باشین , یک نمونه مشترک از DbContext را در بین چند Thread به اشتراک می گذارید و همانطور که مطلع هستین DbContext هیچ گارانتی برای Thread Safe بودن ندارد , شاید بگویید در برنامه من از Thread استفاده نمی شود , اما به یاد داشته باشین , HttpModule و HttpHandler خودشان نوعی Multi Thread می باشند. در این حالت چگونه مدیریت می شود؟

3 - اگر شما از Async Programing استفاده کرده باشین و همچنین از Multi Threading , هر استفاده از Wait , تنها در Thread خود شناخته می شود و در نتیجه گویا شما 2 کوئری Async همزمان را صدا زده باشین و در نتیجه پیام خطای معروف زیر را دریافت خواهید کرد:



A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe


نظرتون در رابطه با موارد ذکر شده چیه و طور میشه این مشکلات رو با این الگو حل کرد؟

anubis_ir
سه شنبه 29 دی 1394, 12:37 عصر
- HttpModule نوعي كپسوله كردن مثلا begin request و end request درخواست جاري هست. يعني در يك ترد جدا اجرا نميشه. در همون ترد درخواست جاري اجرا ميشه و جزئي از اون هست.
- HttpHandler خودش يك درخواست جداگانه رو از صفر شروع مي‌كنه. بنابراين context خاص خودش رو خواهد داشت و كاري به context ساير درخواست‌ها نداره.

parsdarab
سه شنبه 06 بهمن 1394, 16:15 عصر
سلام

منم یه سوال در این مورد دارم
کد به صورت زیر می باشد

روال کلی تابع به صورت زیر می باشد
ما یک گروه داریم این گروه دارای یکسری مجوز هس
حالا ما وقتی که یک عضو رو می خواهیم به گروه اضافه کنیم باید تمام مجوزها رو هم درجدول مورد نظر اضافه کنیم

مشکل کار: کار با الگوی واحد کار است
دستور زیر
var result = _userManager.AddToRoleAsync(userId, roleId).Result;
مثل اینکه خودش جداگانه یک الگوی دیگر داره
من با دیباگ که رفتم جلو بعد از این دستور رکورد در بانک درج می شود
و بعد از اجرای دستور زیر
modelValidation = _uow.SaveAllChanges();
عضو به گروه اضافه می شود
در این بین شاید در هنگام اضافه کردن عضو به گروه مشکلی بیش آید
تکلیف اون رکوردهایی که درج شده اند چی میشه
ناهماهنگی پیش میاد




//گرفتن نام رولهای مربوط به گروه
var roleNames = _roleManager.GetAllCustomRoles().Where(x => roleIds.Contains(x.Id)).Select(x => x.Name).ToList();


//حلقه به تعداد اعضا
foreach (var userId in Ids)
{
BaseUserGroup temp = new BaseUserGroup();
temp.GroupId = groupId;
temp.UserId = userId;
//اضافه نمودن عضو به گروه
_userGroupService.Base_AddOrUpdate(temp);
//حلقه به ازای مجوزهای گروه
foreach (var roleId in roleNames)
{
//برای اختصاص رول به کاربر باید نام رول به عنوان ارگومان داده شود نه کد رکورد
var result = _userManager.AddToRoleAsync(userId, roleId).Result;
}
}
modelValidation = _uow.SaveAllChanges();

salar IT man
سه شنبه 06 بهمن 1394, 17:35 عصر
سلام

منم یه سوال در این مورد دارم
کد به صورت زیر می باشد

روال کلی تابع به صورت زیر می باشد
ما یک گروه داریم این گروه دارای یکسری مجوز هس
حالا ما وقتی که یک عضو رو می خواهیم به گروه اضافه کنیم باید تمام مجوزها رو هم درجدول مورد نظر اضافه کنیم

مشکل کار: کار با الگوی واحد کار است
دستور زیر
var result = _userManager.AddToRoleAsync(userId, roleId).Result;
مثل اینکه خودش جداگانه یک الگوی دیگر داره
من با دیباگ که رفتم جلو بعد از این دستور رکورد در بانک درج می شود
و بعد از اجرای دستور زیر
modelValidation = _uow.SaveAllChanges();
عضو به گروه اضافه می شود
در این بین شاید در هنگام اضافه کردن عضو به گروه مشکلی بیش آید
تکلیف اون رکوردهایی که درج شده اند چی میشه
ناهماهنگی پیش میاد




//گرفتن نام رولهای مربوط به گروه
var roleNames = _roleManager.GetAllCustomRoles().Where(x => roleIds.Contains(x.Id)).Select(x => x.Name).ToList();


//حلقه به تعداد اعضا
foreach (var userId in Ids)
{
BaseUserGroup temp = new BaseUserGroup();
temp.GroupId = groupId;
temp.UserId = userId;
//اضافه نمودن عضو به گروه
_userGroupService.Base_AddOrUpdate(temp);
//حلقه به ازای مجوزهای گروه
foreach (var roleId in roleNames)
{
//برای اختصاص رول به کاربر باید نام رول به عنوان ارگومان داده شود نه کد رکورد
var result = _userManager.AddToRoleAsync(userId, roleId).Result;
}
}
modelValidation = _uow.SaveAllChanges();


مطلب مورد نظر شما مربوط است به الگوی Transaction Per Request (http://www.dotnettips.info/post/2178/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87%E2%80%8C%D8%B3%D8%A 7%D8%B2%DB%8C-%D8%A7%D9%84%DA%AF%D9%88%DB%8C-transaction-per-request-%D8%AF%D8%B1-ef)

parsdarab
چهارشنبه 07 بهمن 1394, 11:13 صبح
سلام

در مورد کد زیر خطای
does not contain definition for assembliy گرفتم
میگه تابع Assembliy در StructureMap.Graph.IAssembliyScanner وجود ندارد.
رفرنس های زیر هم اضافه کردم
using StructureMap;
using StructureMap.Configuration.DSL;
using StructureMap.Graph;



scan.Assembliy("yourAssemblyName");


بعد به جای yourAssemblyName باید دقیقا چی بنویسیم


در مورد کلاس

publicclassTransactionPerRequest : IRunOnEachRequest, IRunOnError, IRunAfterEachRequest{
private readonly IUnitOfWork _uow;
private readonly HttpContextBase _httpContext;
public TransactionPerRequest(IUnitOfWork uow, HttpContextBase httpContext)
{
_uow = uow;
_httpContext = httpContext;
}


void IRunOnEachRequest.Execute()
{
_httpContext.Items["_Transaction"] =
_uow.Database.BeginTransaction(System.Data.Isolati onLevel.ReadCommitted);
}

void IRunOnError.Execute()
{
_httpContext.Items["_Error"] = true;
}

void IRunAfterEachRequest.Execute()
{
var transaction = (DbContextTransaction) _httpContext.Items["_Transaction"];
if (_httpContext.Items["_Error"] != null)
{
transaction.Rollback();
}
else
{
transaction.Commit();
}
}

}


باید در لایه web باشد؟
با تشکر

parsdarab
چهارشنبه 07 بهمن 1394, 12:09 عصر
در مورد خط زیر


_uow.Database.BeginTransaction(System.Data.Isolati onLevel.ReadCommitted);


میگه Database وجو ندارد

و من انون ایتطوری پیاده سازی کردم

ایا درسته؟

public Database database()
{
return this.Database;
}


و نحوه استفاده


_uow.database().BeginTransaction(System.Data.Isola tionLevel.ReadCommitted);

parsdarab
چهارشنبه 07 بهمن 1394, 12:55 عصر
میگم وقتی برنامه ستارت میشه


protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.F ilters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);


setDbInitializer();
//Set current Controller factory as StructureMapControllerFactory
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());


// other code
foreach (var task in SmObjectFactory.Container.GetAllInstances<IRunAtInit>())
{
task.Execute();
}


}

چرا وارد حلقه for نمیشه

من با کامنت کردن تکه کد زیر


//scan.Assembliy("yourAssemblyName");


برنامه اجرا شد.اما
باز هم اتمیک نشده؟

parsdarab
پنج شنبه 08 بهمن 1394, 00:17 صبح
سلام
دوستان
من یه سوال در مورد الگو واحد کار داشتم

به نظر من این درست کار نمی کنه
در کد زیر من هنوز دستور saveChange را فراخونی نکردم اما در بانک اطلاعاتی رکورد درج میشه؟
var result = _userManager.AddToRoleAsync(userId, roleId).Result;

به نظر من این قسمت Identity شبیهRepository عمل میکنه؟

مثلا سرویس های مربوط به Identity مثل _userManager.AddToRoleAsync و _userManager.CreateAsync

یعنی داخل تابع AddToRoleAsync و CreateAsync یک دستور saveChange وجود دارد

parsdarab
پنج شنبه 08 بهمن 1394, 00:36 صبح
ما چطوری میتونیم از تو فایل Global.asax به _uow دسترسی داشته باشیم؟

salar IT man
پنج شنبه 08 بهمن 1394, 20:03 عصر
سلام
دوستان
من یه سوال در مورد الگو واحد کار داشتم

به نظر من این درست کار نمی کنه
در کد زیر من هنوز دستور saveChange را فراخونی نکردم اما در بانک اطلاعاتی رکورد درج میشه؟
var result = _userManager.AddToRoleAsync(userId, roleId).Result;

به نظر من این قسمت Identity شبیهRepository عمل میکنه؟

مثلا سرویس های مربوط به Identity مثل _userManager.AddToRoleAsync و _userManager.CreateAsync

یعنی داخل تابع AddToRoleAsync و CreateAsync یک دستور saveChange وجود دارد

پشت زمینه این متد ها ، متد SaveChanges فراخوانی شده است. سورس باز است (https://aspnetidentity.codeplex.com/SourceControl/latest#Readme.markdown) بهتر است برای تسلط کافی بر روی مباحث آن کمی وقت بذارید و بررسی کنید .

اگر متد مورد نظر را در سورس آن پی گیری کنید به کد زیر خواهید رسید:


/// <summary>
/// Update an entity
/// </summary>
/// <param name="user"></param>
public virtual async Task UpdateAsync(TUser user)
{
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
_userStore.Update(user);
await SaveChanges().WithCurrentCulture();
}

salar IT man
پنج شنبه 08 بهمن 1394, 20:06 عصر
ما چطوری میتونیم از تو فایل Global.asax به _uow دسترسی داشته باشیم؟

همیشه امکان استفاده از الگوی ServiceLocator وجود دارد:

var unitOfWork=ProjectObjectFactory.Container.GetInsta nce<IUnitOfWork>();