اشتراک‌ها
Linq و پارامترهای out
در این پست از اریک لیپرت از عدم تداخل پارامترهای ارسالی از نوع out و عبارت‌های Linq صحبت شده است.
Linq و پارامترهای out
نظرات مطالب
تاریخ شمسی برای blogger !
سلام
- میلادی را هم به روش فارسی اضافه کردم :)

- ضمنا اسکریپت گریس مانکی هم به روز شد تا با آن تداخل نکند.
مطالب
غنی سازی کامپایلر C# 9.0 با افزونه‌ها
از زمانیکه کامپایلر #C، تحت عنوان Roslyn بازنویسی شد، قابلیت افزونه‌پذیری نیز پیدا کرد. برای مثال می‌توان آنالیز کننده‌ای را طراحی کرد که در پروسه‌ی کامپایل متداول کدهای  #C مورد استفاده قرار گرفته و خطاها و یا اخطارهایی را صادر کند که جزئی از پیام‌های استاندارد کامپایلر #C نیستند. در این مطلب نحوه‌ی معرفی آن‌ها را به پروژه‌های جدید NET 5.0.، بررسی می‌کنیم.


معرفی تعدادی آنالیز کننده‌ی کد که به عنوان افزونه‌ی کامپایلر #C قابل استفاده هستند

Microsoft.CodeAnalysis.NetAnalyzers
این افزونه جزئی از SDK دات نت 5 است و نیازی به نصب مجزا را ندارد. البته اگر می‌خواهید نگارش‌های جدیدتر آن‌را پیش از یکی شدن با SDKهای بعدی مورد آزمایش قرار دهید، می‌توان آن‌را به صورت صریحی نیز به کامپایلر معرفی کرد. این افزونه‌ی جایگزین FxCop است و پس از ارائه‌ی آن، FxCop را منسوخ شده اعلام کردند.

Meziantou.Analyzer
یکسری نکات بهبود کیفیت کدها که توسط Meziantou در طی سال‌های متمادی جمع آوری شده‌اند، تبدیل به افزونه‌ی فوق شده‌اند.

Microsoft.VisualStudio.Threading.Analyzers
این افزونه نکاتی را در مورد مشکلات Threading موجود در کدها، گوشزد می‌کند.

Microsoft.CodeAnalysis.BannedApiAnalyzers
با استفاده از این افزونه می‌توان استفاده‌ی از یکسری کدها را ممنوع کرد. برای مثال استفاده‌ی از System.DateTimeOffset.DateTime، در سراسر کدها ممنوع شده و استفاده‌ی از System.DateTimeOffset.UtcDateTime پیشنهاد شود.

AsyncFixer و Asyncify
این دو افزونه، مشکلات متداول در حین کار با کدهای async را گوشزد می‌کنند.

ClrHeapAllocationAnalyzer
این افزونه مکان‌هایی از کد را مشخص می‌کنند که در آن‌ها تخصیص حافظه صورت گرفته‌است. کاهش این مکان‌ها می‌تواند به بالا رفتن کارآیی برنامه کمک کنند.

SonarAnalyzer.CSharp
مجموعه‌ی معروف Sonar، که تعداد قابل ملاحظه‌ای بررسی کننده‌ی کد را به پروژه‌ی شما اضافه می‌کنند.


روش معرفی سراسری افزونه‌های فوق به تمام پروژه‌های یک Solution

می‌توان تنظیمات زیر را به یک تک پروژه اعمال کرد که برای اینکار نیاز است فایل csproj آن‌را ویرایش نمود و یا می‌توان یک تک فایل ویژه را به نام Directory.Build.props ایجاد کرد و آن‌را به صورت زیر تکمیل نمود. محل قرارگیری این فایل، در ریشه‌ی Solution و در کنار فایل sln می‌باشد.
<Project>
  <PropertyGroup>
    <AnalysisLevel>latest</AnalysisLevel>
    <AnalysisMode>AllEnabledByDefault</AnalysisMode>
    <CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
    <EnableNETAnalyzers>true</EnableNETAnalyzers>
    <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
    <Nullable>enable</Nullable>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
    <RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
    <!--
      CA2007: Consider calling ConfigureAwait on the awaited task
      MA0004: Use Task.ConfigureAwait(false) as the current SynchronizationContext is not needed
      CA1056: Change the type of property 'Url' from 'string' to 'System.Uri'
      CA1054: Change the type of parameter of the method to allow a Uri to be passed as a 'System.Uri' object
      CA1055: Change the return type of method from 'string' to 'System.Uri'
    -->
    <NoWarn>$(NoWarn);CA2007;CA1056;CA1054;CA1055;MA0004</NoWarn>
    <NoError>$(NoError);CA2007;CA1056;CA1054;CA1055;MA0004</NoError>
    <Deterministic>true</Deterministic>
    <Features>strict</Features>
    <ReportAnalyzer>true</ReportAnalyzer>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

    <PackageReference Include="Meziantou.Analyzer" Version="1.0.639">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

    <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.8.55">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

    <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.2">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

    <PackageReference Include="AsyncFixer" Version="1.3.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

    <PackageReference Include="Asyncify" Version="0.9.7">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

    <PackageReference Include="ClrHeapAllocationAnalyzer" Version="3.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

    <PackageReference Include="SonarAnalyzer.CSharp" Version="8.16.0.25740">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" Link="Properties/BannedSymbols.txt" />
  </ItemGroup>
</Project>
توضیحات:
- در تنظیمات فوق، مواردی مانند AnalysisLevel، در مطلب «کامپایلر C# 9.0، خطاها و اخطارهای بیشتری را نمایش می‌دهد» پیشتر بررسی شده‌اند.
- در اینجا Nullable به true تنظیم شده‌است. اگر قرار است یک پروژه‌ی جدید را شروع کنید، بهتر است این ویژگی را نیز فعال کنید. بسیاری از API‌های دات نت 5 جهت مشخص سازی خروجی نال و یا غیرنال آن‌ها، بازنویسی و تکمیل شده‌اند و بدون استفاده از این ویژگی، بسیاری از راهنمایی‌های ارزنده‌ی دات نت 5 را از دست خواهید داد. اساسا بدون فعالسازی این ویژگی، از قابلیت‌های #C مدرن استفاده نمی‌کنید.
- وجود این PackageReference ها، به معنای بالا رفتن حجم نهایی قابل ارائه‌ی پروژه نیست؛ چون به صورت PrivateAssets و analyzers تعریف شده‌اند و فقط در حین پروسه‌ی کامپایل، جهت ارائه‌ی راهنمایی‌های بیشتر، تاثیرگذار خواهند بود.
- این تنظیمات طوری چیده شده‌اند که تا حد ممکن «درد آور» باشند! برای اینکار CodeAnalysisTreatWarningsAsErrors و TreatWarningsAsErrors به true تظیم شده‌اند تا حتی اخطارها نیز به صورت خطای کامپایلر گزارش شوند؛ تا مجبور به رفع آن‌ها شویم.
- در اینجا فایل BannedSymbols.txt را نیز مشاهده می‌کنید که مرتبط است به BannedApiAnalyzers. می‌توان در کنار فایل Directory.Build.props، فایل جدید BannedSymbols.txt را با این محتوا ایجاد کرد:
# https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md
P:System.DateTime.Now;Use System.DateTime.UtcNow instead
P:System.DateTimeOffset.Now;Use System.DateTimeOffset.UtcNow instead
P:System.DateTimeOffset.DateTime;Use System.DateTimeOffset.UtcDateTime instead
در این حالت برای مثال، از استفاده‌ی از DateTime.Now منع شده و وادار به استفاده‌ی از DateTime.UtcNow می‌شوید.


روش کاهش تعداد خطاهای نمایش داده شده

اگر از فایل Directory.Build.props فوق استفاده کرده و یکبار دستور dotnet restore را جهت بازیابی وابستگی‌های آن اجرا کنید، با تعداد خطاهایی که در IDE خود مشاهده خواهید کرد، شگفت‌زده خواهید شد! به همین جهت برای کنترل آن‌ها می‌توان فایل جدید editorconfig. را به نحو زیر در کنار فایل Directory.Build.props ایجاد و تکمیل کرد:
[*.cs]

# MA0026 : Complete the task
dotnet_diagnostic.MA0026.severity = suggestion

# CA1308: In method 'urlToLower', replace the call to 'ToLowerInvariant' with 'ToUpperInvariant' (CA1308)
dotnet_diagnostic.CA1308.severity = suggestion

# CA1040: Avoid empty interfaces
dotnet_diagnostic.CA1040.severity = suggestion

# CA1829 Use the "Count" property instead of Enumerable.Count()
dotnet_diagnostic.CA1829.severity = suggestion

# Use 'Count' property here instead.
dotnet_diagnostic.S2971.severity = suggestion

# S1135 : Complete the task
dotnet_diagnostic.S1135.severity = suggestion

# S2479: Replace the control character at position 7 by its escape sequence
dotnet_diagnostic.S2479.severity = suggestion

# CA2007: Consider calling ConfigureAwait on the awaited task
dotnet_diagnostic.CA2007.severity = none

# MA0004: Use Task.ConfigureAwait(false) as the current SynchronizationContext is not needed
dotnet_diagnostic.MA0004.severity = none

# CA1056: Change the type of property 'Url' from 'string' to 'System.Uri'
dotnet_diagnostic.CA1056.severity = suggestion

# CA1054: Change the type of parameter of the method to allow a Uri to be passed as a 'System.Uri' object
dotnet_diagnostic.CA1054.severity = suggestion

# CA1055: Change the return type of method from 'string' to 'System.Uri'
dotnet_diagnostic.CA1055.severity = suggestion

# S4457: Split this method into two, one handling parameters check and the other handling the asynchronous code.
dotnet_diagnostic.S4457.severity = none

# AsyncFixer01: Unnecessary async/await usage
dotnet_diagnostic.AsyncFixer01.severity = suggestion

# AsyncFixer02: Long-running or blocking operations inside an async method
dotnet_diagnostic.AsyncFixer02.severity = error

# VSTHRD103: Call async methods when in an async method
dotnet_diagnostic.VSTHRD103.severity = error

# AsyncFixer03: Fire & forget async void methods
dotnet_diagnostic.AsyncFixer03.severity = error

# VSTHRD100: Avoid async void methods
dotnet_diagnostic.VSTHRD100.severity = error

# VSTHRD101: Avoid unsupported async delegates
dotnet_diagnostic.VSTHRD101.severity = error

# VSTHRD107: Await Task within using expression
dotnet_diagnostic.VSTHRD107.severity = error

# AsyncFixer04: Fire & forget async call inside a using block
dotnet_diagnostic.AsyncFixer04.severity = error

# VSTHRD110: Observe result of async calls
dotnet_diagnostic.VSTHRD110.severity = error

# VSTHRD002: Avoid problematic synchronous waits
dotnet_diagnostic.VSTHRD002.severity = suggestion

# MA0045: Do not use blocking call (make method async)
dotnet_diagnostic.MA0045.severity = suggestion

# AsyncifyInvocation: Use Task Async
dotnet_diagnostic.AsyncifyInvocation.severity = error

# AsyncifyVariable: Use Task Async
dotnet_diagnostic.AsyncifyVariable.severity = error

# VSTHRD111: Use ConfigureAwait(bool)
dotnet_diagnostic.VSTHRD111.severity = none

# MA0022: Return Task.FromResult instead of returning null
dotnet_diagnostic.MA0022.severity = error

# VSTHRD114: Avoid returning a null Task
dotnet_diagnostic.VSTHRD114.severity = error

# VSTHRD200: Use "Async" suffix for async methods
dotnet_diagnostic.VSTHRD200.severity = suggestion

# MA0040: Specify a cancellation token
dotnet_diagnostic.MA0032.severity = suggestion

# MA0040: Flow the cancellation token when available
dotnet_diagnostic.MA0040.severity = suggestion

# MA0079: Use a cancellation token using .WithCancellation()
dotnet_diagnostic.MA0079.severity = suggestion

# MA0080: Use a cancellation token using .WithCancellation()
dotnet_diagnostic.MA0080.severity = error

#AsyncFixer05: Downcasting from a nested task to an outer task.
dotnet_diagnostic.AsyncFixer05.severity = error

# ClrHeapAllocationAnalyzer ----------------------------------------------------
# HAA0301: Closure Allocation Source
dotnet_diagnostic.HAA0301.severity = suggestion

# HAA0601: Value type to reference type conversion causing boxing allocation
dotnet_diagnostic.HAA0601.severity = suggestion

# HAA0302: Display class allocation to capture closure
dotnet_diagnostic.HAA0302.severity = suggestion

# HAA0101: Array allocation for params parameter
dotnet_diagnostic.HAA0101.severity = suggestion

# HAA0603: Delegate allocation from a method group
dotnet_diagnostic.HAA0603.severity = suggestion

# HAA0602: Delegate on struct instance caused a boxing allocation
dotnet_diagnostic.HAA0602.severity = suggestion

# HAA0401: Possible allocation of reference type enumerator
dotnet_diagnostic.HAA0401.severity = silent

# HAA0303: Lambda or anonymous method in a generic method allocates a delegate instance
dotnet_diagnostic.HAA0303.severity = silent

# HAA0102: Non-overridden virtual method call on value type
dotnet_diagnostic.HAA0102.severity = silent

# HAA0502: Explicit new reference type allocation
dotnet_diagnostic.HAA0502.severity = none

# HAA0505: Initializer reference type allocation
dotnet_diagnostic.HAA0505.severity = silent
روش کار هم به صورت است که برای مثال در IDE خود (حتی با VSCode هم کار می‌کند)، خطای کامپایلر مثلا CA1308 را مشاهده می‌کنید که عنوان کرده‌است بجای ToLowerInvariant از ToUpperInvariant استفاده کنید. اگر با این پیشنهاد موافق نیستید (عین خطا را به صورت C# CA1308 در گوگل جستجو کنید؛ توضیحات مایکروسافت را در مورد آن خواهید یافت)، یک سطر شروع شده‌ی با dotnet_diagnostic و سپس ID خطا را به صورت زیر، به فایل editorconfig. یاد شده، اضافه کنید:
dotnet_diagnostic.CA1308.severity = suggestion
به این ترتیب هنوز هم این مورد را به صورت یک پیشنهاد مشاهده خواهید کرد، اما دیگر جزو خطاهای کامپایلر گزارش نمی‌شود. اگر خواستید که به طور کامل ندید گرفته شود، مقدار آن‌را بجای suggestion به none تغییر دهید.

یک نکته: در ویندوز نمی‌توانید یک فایل تنها پسوند دار را به صورت معمولی در windows explorer ایجاد کنید. نام این فایل را به صورت .editorconfig. با دو نقطه‌ی ابتدایی و انتهایی وارد کنید. خود ویندوز نقطه‌ی پایانی را حذف می‌کند.


روش صرفنظر کردن از یک خطا، تنها در یک قسمت از کد

فرض کنید نمی‌خواهید خطای CA1052 را تبدیل به یک suggestion سراسری کنید و فقط می‌خواهید که در قطعه‌ی خاصی از کدهای خود، آن‌را خاموش کنید. به همین جهت بجای اضافه کردن آن به فایل editorconfig.، باید از ویژگی SuppressMessage به صورت زیر استفاده نمائید:
[SuppressMessage("Microsoft.Usage", "CA1052:Type 'Program' is a static holder type but is neither static nor NotInheritable",
  Justification = "We need it for our integration tests this way.")]
[SuppressMessage("Microsoft.Usage", "RCS1102:Type 'Program' is a static holder type but is neither static nor NotInheritable",
  Justification = "We need it for our integration tests this way.")]
[SuppressMessage("Microsoft.Usage", "S1118:Type 'Program' is a static holder type but is neither static nor NotInheritable",
  Justification = "We need it for our integration tests this way.")]
public class Program { }
در اینجا پارامتر اول با Microsoft.Usage مقدار دهی می‌شود. پارامتر دوم آن باید حاوی ID خطا باشد. در صورت تمایل می‌توانید دلیل خاموش کردن این خطا را در قسمت Justification وارد کنید.
نظرات مطالب
طراحی گزارش در Stimulsoft Reports.Net – بخش 2
سلام و خسته نباشید
من هنوز در این بحث گزارش گیری کاملا مبتدی هستم. چون می‌خواستم تازه کارم رو شروع کنم دنبال انتخاب انتخاب نرم افزار مناسب برای گزارشگیری C# در محیط ویندوز بودم. یک سری مطالب کپی شده و تکراری در اینترنت رو دیدم، دوست داشتم نظر تخصصی و شخصی خودتون رو بدونم. من اول دنبال کریستال بودم، ولی بعدش دیدم که ظاهرا استیمول هم نرم افزار معروفیه، میشه کمکم کنید؟
بی نهایت ممنون از سایت خوبتون
مطالب
اصول پایگاه داده - تراکنش ها
در این مقاله آموزشی قصد داریم به یکی از مهمترین و اساسی‌ترین مفاهیم تعریف شده در پایگاه داده بنام تراکنش‌ها بپردازیم. بعنوان تعریف می‌توان اینگونه بیان نمود که تراکنش یک واحد کاری منطقی است که عملی را بر روی پایگاه داده انجام می‌دهد. عموما تراکنش‌ها دنباله ای از عملیات پایگاه داده هستند که رویه هم رفته انجام یک کار یا وظیفه را بر عهده دارند. نکته مهمی که در مورد تراکنش‌ها مطرح می‌شود اینست که آنها باید به گونه ای مدیریت شوند که پایگاه داده را از یک وضعیت سازگار و درست (consistent) به وضعیت سازگار دیگری ببرند. به بیان دیگر اگر تراکنش از چند عملیات تشکیل شده باشد، پس از پایان اجرای تمامی عملیات مربوط به تراکنش نباید در داده‌های پایگاه داده هیچ تناقضی با قوانین پایگاه داده (integrity rules) بوجود بیاید. مزیت استفاده از تراکنش نیز همین مسئله است که به توسعه دهنده نرم افزار این اطمینان را می‌دهد که صحت و درستی پایگاه داده در اثر اجرای دستورات او از بین نخواهد رفت. علاوه بر آن اگر در حین اجرای یکی از دستورات خللی ایجاد گردد، پایگاه داده دوباره به وضعیت سازگار قبلی خود باز گردانده خواهد شد. نسل‌های اولیه سیستم‌های مدیریت پایگاه داده فاقد پیاده سازی تراکنش بودند و بهمین دلیل توسعه دهندگان کار بسیار مشکلی در شبیه سازی این واحد‌های یکپارچه منطقی داشتند. خوشبختانه اکثر DBMS‌های امروزی این مفهوم مهم را پشتیبانی می‌کنند و نیازی به نگرانی در مورد پیاده سازی آن نیست. تنها کاری که لازم است انجام گیرد کسب مهارت در زمینه استفاده از آنهاست.
تعریف تراکنش‌ها و مشخص کردن عملیات موجود در آنها اغلب توسط خود توسعه دهنده برنامه صورت می‌گیرد. اوست که تعیین می‌کند تراکنشش باید چه عملیاتی را با چه ترتیبی انجام دهد. اما در کنار این قسم از تراکنش‌ها که توسط کاربران تعریف می‌شود، تراکنش‌های دیگری نیز وجود دارند که توسط خود سیستم مدیریت پایگاه داده تعریف می‌شوند. به این قبیل تراکنش‌ها که واحد‌های کاری بسیار کوچک و عموما تجزیه ناپذیری هستند تراکنش‌های خودکار یا auto transactions گفته می‌شود. بعنوان مثال اگر ما تراکنشی را تعریف کرده باشیم که شامل یک عمل خواندن و یک عمل درج باشد، در هنگام اجرا سیستم این تراکنش را به دو تراکنش کوچکتر می‌شکند که در یکی عمل خواندن و در دیگری عملی نوشتن و درج را انجام می‌دهد. البته توجه داشته باشید که اگر چه این دو عملیات جدا و مستقل از هم اجرا می‌شوند اما رابطه منطقی آنها با یکدیگر  حفظ می‌شود و در صورت خللی در یکی از آنها اثر دیگری نیز بازگردانده شده و پایگاه داده دوباره به حالت قبل از جرا برگردانده می‌شود. به این کار عمل undo شدن تراکنش گفته می‌شود. 
 
گفتیم که تعریف تراکنش توسط کاربر صورت می‌پذیرد و مدیریت آن بر عهده پایگاه داده قرار می‌گیرد. در این میان نکته حائز اهمیتی وجود دارد که در اینجا باید به آن اشاره شود. اندازه تراکنش نقشی بسیار موثر در کارایی پایگاه داده ایفا می‌کند. توجه داشته باشید که اندازه تراکنش‌ها نباید خیلی بزرگ باشد. چراکه منجر به بزرگ شدن بیرویه فایل مربوط به ثبت وقایع پایگاه داده (log file) می‌گردد. تمامی علیات تاثیر گذار بر روی پایگاه داده در این فایل ثبت می‌شوند تا در موقع لزوم بتوان با استفاده از عمل بازیابی و ترمیم پایگاه داده (recovery) را انجام داد. بزرگ بودن این فایل در هنگام ترمیم می‌تواند بر روی کارایی تاثیر گذار باشد. علاوه بر این موضوع اندازه تراکنش‌ها اثر سوء دیگری نیز می‌تواند در پی داشته باشد و آن محدود نمودن درجه همروندی است. یعنی اگر اندازه تراکنش بیش از حد معمول باشد ممکن است بر روی تعداد تراکنش هایی که می‌توانند بطور موازی و همزمان اجرا شوند تاثیر منفی بگذارد. چرا که معمولا در آغاز تراکنش بر روی منابعی که مورد استفاده تراکنش قرار می‌گیرد قفل گذاری می‌شود تا بگونه ای مسئله نواحی بحرانی حل شود. این قفل‌ها زمانی آزاد می‌شوند که تمامی عملیات داخل تراکنش بطور کامل اجرا شده باشند یا اینکه مشکلی در حین اجرا بوجود آید. در این صورت هرچه تراکنش بزرگ‌تر باشد اجرای آن بیشتر طول خواهد کشید و در نتیجه قفل‌های آن نیز دیر‌تر آزاد می‌شوند. بدین ترتیب سایر تراکنش هایی که می‌خواهند از منابع مشترک استفاده کنند باید تا پایان اجرای تراکنش بزرگ ما منتظر بمانند. این مسئله یعنی کاهش درجه اجرای موازی با همروندی که اگر در سیستم‌های بزرگ به آن دقت نشود به گلوگاهی تبدیل خواهد شد و کارایی را به نحو قابل توجهی کاهش می‌دهد.
 
 تعریف تراکنش‌ها :
بدنه اصلی هر تراکنش را چهار کلمه کلیدی تشکیل می‌دهند که البته ممکن است صریحا در تعریف توسط کاربر لحاظ نشوند اما این چهار کلمه کلیدی باید در تمامی تراکنش‌ها چه بصورت صریح و چه بصورت ضمنی آورده شوند. این کلمات عبارتند از BEGIN TRANSACTION، END TRANSACTION، ROLLBACK و COMMIT. کلمات کلیدی BEGIN TRANSACTION و END TRANSACTION  همانطور که از نامشان پیداست آغاز و پایان یک تراکنش را نشان می‌دهد. اینکه تراکنش از چه نقطه ای آغاز و در چه نقطه ای به پایان رسیده است برای مدیریت آن بسیار مهم و حیاتی است بخصوص در مواقعی که در حین انجام مشکلی پیش بیاید. از کلمه کلیدی ROLLBACK هنگامی استفاده می‌کنیم که بخواهیم تغییراتی که تا این لحظه بر روی پایگاه داده صورت گرفته است را مجددا بی اثر کنیم و پایگاه داده را به حالت پیش از شروع تراکنش بازگردانیم. توجه داشته باشید که در برخی از مواقع ممکن است این کلمه را خودمان در بدنه تراکنش مستقیما قرار دهیم. بعنوان مثال یک خطای منطقی را در بخشی از روال انجام تراکنش با یک عبارت شرطی تشخیص می‌دهیم و با استفاده از ROLLBACK به مدیریت پایگاه داده اعلام می‌کنیم که عملیات بازگردانی را انجام بده. گاهی ممکن است ما صریحا این کلمه را در تراکنش نیاورده باشیم اما درحین انجام تراکنش خطایی رخ دهد، در این صورت خود سیستم مدیریت پایگاه داده خطا را شناسایی کرده و عملیات مربوط به ROLLBACK را انجام می‌دهد تا صحت و سازگاری پایگاه داده حفظ گردد. کلمه کلیدی COMMIT نیز باید در انتهای تراکنش آورده شود تا به مدیریت پایگاه داده اعلام شود که عملیات کامل شده است و تغییرات باید در پایگاه داده بطور فیزیکی اعمال شوند. توجه داشته باشید که تا زمانی که مدیریت پایگاه داده به دستور COMMIT نرسیده باشد، تغییرات را جهت اعمال بر روی حافظه فیزیکی به واحد مدیریت حافظه نمی‌دهد و بنابراین این تغییرات تا پیش از COMMIT از چشم سایر کاربران مخفی خواهد ماند.
 
نکته ای که در اینجا وجود دارد این است که فرمان COMMIT به معنی این نیست که بلافاصله تغییرات بر روی دیسک و حافظه جانبی نوشته می‌شود. بلکه به این معنی است که تمامی عملیات تراکنش با موفقیت انجام شده است و سیستم مدیریت پایگاه می‌تواند آنها را برای نوشته شدن در حافظه جانبی به واحد مدیریت حافظه تحویل دهد. در اینجاست که یکی دیگر از پیچیدگی‌های طراحی سیستم مدیریت پایگاه داده روشن می‌شود و آن اینست که این سیستم باید بنحوی این داده‌ها را در فاصله بین COMMIT و نوشته شدن در حافظه برای سایر کاربران قابل مشاهده نماید. 
 
در ادامه نمونه ای از یک تراکنش را مشاهده می‌کنید :
BEGIN TRANSACTION;
INSERT INTO SP RELATION {S#  S#(‘S5’), P#  P#(‘P1’), 
                    QTY  QTY(1000)}};
IF any error occurred THEN GOTO UNDO; END IF;
UPDATE P WHERE P# = P#(‘P1’)
    TOTAL:=TOTAL + QTY(1000);
IF any error occurred THEN GOTO UNDO; END IF;
COMMIT;
GOTO FINISH;
UNDO:  ROLLBACK;
FINISH: RETURN;
همانطور که مشاهده می‌کنید تراکنش بالا دارای تمامی بخش‌های اصلی تراکنش که ذکر شد می‌باشد. البته این امکان وجود دارد که صراحتا این کلمات را در تعریف بدنه تراکنش نیاوریم. بعنوان مثال می‌توان از آوردن COMMIT صرف نظر کرد. در این صورت خود سیستم مدیریت پایگاه داده پس از اجرای آخرین دستور تراکنش در صورتی که هیچ خطایی رخ نداده باشد بطور خودکار عمل COMMIT را انجام می‌دهد. این امر در مورد ROLLBACK و END نیز صادق است. اما در مورد BEGIN TRANSACTION نکته ای وجود دارد و آن اینست که ما باید به پایگاه داده اعلام کنیم که بطور خودکار در پایان یک تراکنش برای شروع تراکنش بعدی BEGIN TRANSACTION را لحاظ کند. این کار را باید با دستور SET IMPLICIT TRANSACTION ON انجام دهیم.
گفتیم که وقوع خطا می‌تواند توسط برنامه نویس شناسایی شود و یا توسط سیستم. یک نمونه از تشخیص خطا توسط برنامه نویس را در مثال بالا مشاهده می‌کنید. عموما دراین قبیل خطا‌ها پس از انجام عمل ROLLBACK تراکنش UNDO شده و اجرای آن متوقف می‌شود که اصطلاحا می‌گوییم تراکنش ABORT می‌شود. اما در مورد خطاهایی که خود سیستم تشخیص می‌دهد وضع به این منوال نیست. در شرایط خطا، سیستم پس از UNDO کردن تراکنش عموما آن را ABORT نمی‌کند بلکه مجددا اجرا می‌کند که به این عمل REDO گفته می‌شود. در بخش‌های بعدی بطور کامل در مورد دو عمل REDO  و UNDO بحث خواهیم کرد.
 
ویژگی‌های تراکنش‌ها :
هر تراکنشی که در سیستم اجرا میشود باید دارای چهار ویژگی باشد. در حقیقت این ویژگی‌ها باید به نحوی تامین شوند تا مقصود و هدف کلی تراکنش‌ها که بردن پایگاه داده از یک وضعیت صحیح به وضعیت صحیح دیگری است برآورده شود. در ادامه هر کدام را یک به یک شرح می‌دهیم :
 
Atomicity:
اولین ویژگی ای که یک تراکنش باید داشته باشد اینست که اثری که بر روی پایگاه داده ما می‌گذارد اثری کامل و بدون نقص باشد. به این معنا که اگر قرار است مجموعه از عملیات تغییراتی را اعمال کنند باید تمامی آن تغییرات بر روی جداول اعمال شوند. در صورتی که حتی یکی از عملیات با مشکل مواجه شود باید تاثیرات عملیات قبلی بازگردانده شوند. به بیانی ساده‌تر در تراکنش یا تمامی عملیات باید بطور کامل انجام شوند و یا هیچ یک از آنها نباید اجرا شده و اثرگذار باشند. به این ویژگی Atomicity گفته می‌شود.
 
توجه داشته باشید که در حین اجرای یک تراکنش احتمالا پایگاه داده به وضعیت غیر سازگار و نادرست خواهد رفت. یکی از وظایف سیستم مدیریت پایگاه داده اینست که این وضعیت ناسازگار را از دید سایر تراکنش‌ها مخفی بسازد تا زمانی که تراکنش COMMIT شود.
 
در مورد Atomicity در برخی مقالات و مطالب آموزشی گفته می‌شود که این مفهوم یعنی تراکنش نباید قابل شکسته شدن باشد که این تعریف چندان صحیحی از Atomicity نمی‌باشد. چراکه یک تراکنش در حین اجرا ممکن است بار‌ها و بارها شکسته شود و یا از یک تراکنش بر روی تراکنش دیگری سوئیچ شود. بنابراین مراد از Atomicity همان واحد کاری کامل است نه واحد کاری غیر قابل شکسته شدن.
 
 
Consistency:
تراکنش باید تغییرات را به گونه ای اعمال کند که پایگاه داده را از وضعیت صحیح به وضعیت صحیح دیگری ببرد.از آنجا که صحت پایگاه داده را قوانین جامعیت پایگاه داده (integrity rules) تضمین می‌کنند بنابراین تراکنش باید تغییرات را بگونه ای اعمال کند که این قوانین نقض نشوند. به این خاصیت از تراکنش‌ها Consistency گفته می‌شود.
 
Isolation:
عموما برنامه‌های مبتنی بر پایگاه در دنیای واقعی برنامه هایی چند کاربره هستند که در برخی از آنها ممکن است میلیون‌ها تراکنش بطور همزمان با یکدیگر در حال اجرا باشند. در چنین حجم بالایی یکی از مسائلی که مطرح می‌شود اینست که تراکنش‌های موازی تاثیر سوئی بر روی یکدیگر نداشته باشند. بعنوان مثال یکی از مشکلاتی که در اجرای همروند و موازی تراکنش‌ها ممکن است رخ دهد مشکل lost update می‌باشد. بر همین اساس یکی دیگر از ویژگی هایی که یک تراکنش باید داشته باشد که اینست که اثر سوئی بر روی تراکنش‌های همروند دیگر نداشته باشد. به این ویژگی Isolation گفته می‌شود.
در مورد ایزولاسیون (isolation) تراکنش‌ها باید گفت که ایزولاسیون سطوح و درجه بندی هایی دارد که هر کدام از این سطوح مشخص می‌کنند که تراکنش‌ها تا چه حدی اجازه دارند بر روی هم تاثیر گذار باشند. در واقع این سطوح، میزان عایق بندی تراکنش‌ها را نسبت به یکدیگر مشخص می‌کنند. هرچه درجه ایزولاسیون بالاتر باشند به این معنی است که تراکنش‌ها تاثیر کمتری بر روی یکدیگر خواهند داشت. خوب در ظاهر ممکن است این قضیه بسیار خوب در نظر بیاید چرا که به ما اطمینان  می دهد که اثر ناخواسته ای بر روی یکدیگر نخواهند داشت. اما باید این نکته را نیز در نظر بگیریم که هر چه درجه ایزولاسیون بالاتر باشد درجه همروندی (concurrency) پایین می‌آید و این به معنای کاهش امکان پردازش موازی تراکنش‌ها می‌باشد. این مسئله در مورد پایگاه‌های داده بسیار بزرگ که میلیون‌ها تراکنش همزمان در خواست اجرا داده می‌شوند به یک مسئله بحرانی و یک گلوگاه می‌تواند تبدیل شود. بنابراین تعیین درجه ایزولاسیون بسیار مهم است و باید با درنظر گرفته شرایط پروژه انجام گیرد. 
اینکه پایگاه داده ما در چه سطحی از ایزولاسیون باید عمل نماید توسط کاربر تعیین می‌شود. البته بحث در مورد ارجای موازی تراکنش‌ها و ایزولاسیون آنها بسیار مفصل است و انشاالله در مطلبی دیگر به آن خواهیم پرداخت.
 
 
Durability:
تغییراتی که تراکنش‌ها بر روی پایگاه داده می‌گذارند باید بعد از COMMIT شدن آن پایدار و قابل مشاهده باشند. به این خاصیت durability گفته می‌شود.
 
وضعیت‌های یک تراکنش :
تراکنش‌ها در سیستم همانند یک موجودیت (entity) فعال است هستند. همانطور که می‌دانید ساده‌ترین موجودیت فعال در سیستم فرآیند‌ها (process) می‌باشند که cpu را بعنوان یک ابزار در اختیار گرفته و وظایفی را انجام می‌دهند. تراکنش نیز یک موجودیت فعال می‌باشد و همانند سایر موجودیت‌های فعال دارای وضعیت هایی (state) می‌باشند که در ادامه هریک شرح داده شده اند :
 
فعال (Active) : تراکنشی که در حالت اجرا است در وضعیت فعال می‌باشد.
کامیت جزئی (Partially Committed): پس از اجرای آخرین دستور تراکنش به وضعیت کامیت جزئی می‌رود.
شکست (Failed): در این وضعیت، در روند اجرا خطایی رخ داده و اجرای ادامه تراکنش امکان پذیر نمی‌باشد.
خاتمه (Aborted): پس از تشخیص خطا تراکنش می‌تواند به وضعیت Aborted که در انجا اجرا متوفق شده و تغییرات ROLLBACK می‌شوند.
Committed: در این وضعیت اجرای تراکنش با موفقیت انجام شده و تراکنش پایان می‌پذیرد.
 
در ادامه نمودار حالت تراکنش‌ها نشاد داده شده است :


نکته ای که در اینجا لازم به ذکر است اینست که در حالت پس از حالت شکست به دو شکل امکان ادامه کار وجود دارد. در صورتی که خطای منطقی در تراکنش دیده شود که عموما توسط کاربر تشخیص داده می‌شود تراکش پس از شکست به حالت خاتمه برده می‌شود و کار تمام است. اما در برخی از شرایط خطایی سیستم توسط خود سیستم رخ می‌دهد. که در چنین حالاتی پس از شکست تراکنش مجددا تراکنش ممکن است به حالت فعال برگردانده شود و اجرای ان دوباره از ابتدای تراکنش شروع شود. به این وضعیت اصطلاحا REDO شدن تراکنش گفته می‌شود که در بخش RECOVERY و ترمیم پایگاه داده باید به آن پرداخته شود.
 
اعمال زمان COMMIT:
در زمان COMMIT (بصورت صریح و یا ضمنی)  باید اعمالی انجام شود که در اینجا به آن می‌پردازیم. اولین کاری که صورت می‌گیرد اینست که سیگنالی به DBMS ارسال می‌شود مبنی بر اینکه تراکنش با موفقیت به پایان رسیده است. پس از اینکار سیستم مدیریت پایگاه داده شروع به آزاد کردن قفل هایی می‌کند که در طول اجرای تراکنش بر روی منابع مختلف پایگاه داده زده شده است تا از تاثیر سوء تراکنش‌ها بر روی یکدیگر جلوگیری به عمل آید. علاوه بر کار ذکر شده تغییراتی که توسط تراکنش داده شده است باید پایدار و قابل رویت توسط سایر تراکنش‌ها گردد.
همانطور که در بخش ابتدایی این مطلب آموزشی اشاره کردیم COMMIT به معنی نوشته شدن تغییرات بر روی دیسک سخت نیست. سیستم مدیریت پایگاه داده تنها درخواست نوشتن داده‌ها را به سیستم مدیریت حافظه می‌دهد و نوشتن ان بر عهده مدیریت حافظه می‌باشد. سیستم مدیریت پایگاه داده باید اطلاع داشته باشد که چه تغییراتی نوشته شده است و چه تغییراتی هنوز در حافظه نوشته نشده است. بنابراین یکی دیگر از پیچیدگی‌های طراحی سیستم‌های مدیریت پایگاه داده اینست که تغییراتی را برای سایرین قابل رویت کند که هنوز در حافظه سخت نوشته نشده است.
 
اعمال زمان ROLLBACK:
در زمان ROLLBACK ناموفق بودن تراکنش باید به DBMS اطلاع داده شود. پس از انکه سیستم مدیریت پایگاه داده مطلع شد تمامی تغییرات اعمال شده تا آن لحظه را UNDO می‌کند. البته توجه داشته باشید که در این زمان همانند زمان COMMIT قفل‌ها نیز آزاد می‌شوند تا سایر تراکنش‌ها بتوانند از منابع در اختیار این تراکنش استفاده کنند و درجه همروندی پایین نیاید.
 
پردازش پیام‌ها در زمان اجرای تراکنش‌ها :
به مثال زیر توجه کنید. 

 Read Sav_Amt
  Sav_Amt := Sav-Amt - 500
    if Sav-Amt <0 then do
       put (“insufficient fund”)
       rollback
       end
    else do
      Write Sav_Amt
      Read Chk_Amt
      Chk_Amt := Chk_Amt + 500
      Write Chk-Amt
      put (“transfer complete”)
End transaction
در تراکنش بالا مبلغ 500 دلار از حساب فردی برداشته شده و به حساب دیگر او منتقل می‌شود. همانطور که مشاهده می‌کنید در خلال اجرای یک تراکنش ممکن است پیام هایی را به کاربر نمایش دهیم. حال در نظر بگیرید که در حین اجرا ما پیامی را در خروجی نمایش می‌دهیم و پس از آن تراکنش با شکست مواجه شده و ROLLBACK می‌گردد. در این شرایط پیامی به کاربر مبنی بر انتقال موفق نمایش داده شده است در حالی که در عمل تراکنش با شکست رو به رو شده است. برای حل این مشکل در ضمن کار پیام‌های مختلفی که در خروجی باید نمایش داده شوند بافر می‌شوند تا پس از COMMIT یا ROLLBACK شدن به کاربر نمایش داده شوند. توجه داشته باشید که در زمان  بافر کردن پیام ها، انها در دو گره پیام‌های مربوط به COMMIT و پیام‌های زمان ROLLBACK تقسیم می‌شوند تا هرکدام در شرایط خود نمایش داد شوند. این عمل توسط زیر سیستمی از DBMS بنام سیستم مدیریت ارتباطات داده ای (Data Communication Manager) انجام می‌گیرد.
 
انواع تراکنش‌ها :
تراکنش‌ها انواع و اقسام مختلفی دارند که به سبب پیچیدگی بعضی از آنها به لحاظ پیاده سازی ممکن است آنها را در برخی از پایگاه داده‌ها نداشته باشیم.
 
Flat Transactions:
ساده‌ترین نوع تراکنش‌ها می‌باشند که در تمامی پایگاه‌های داده پشتیبانی می‌شوند و مثال هایی که تا کنون در این نقاله زده شد از این دست می‌باشند.
 
Distributed Transactions:
این قبیل تراکنش‌ها مربوط به پایگاه داده‌های توزیع شده می‌باشند که داده‌های آنها بر روی ماشین‌های مختلفی قرار دارند. بر روی هریک از این ماشین‌ها ممکن است DBMS‌های مختلفی نیز نصب شده باشد که هر یک سیستم مدیریتی مربطو به خود را دارند. از آنجایی که هر یک از این ماشین‌ها یک سیستم مدیریت پایگاه داده مستقل دارند بنابراین قوانین جامعیتی محلی ای را نیز باید لحاظ نمایند. البته باید توجه داشت که علاوع بر این قوانین محلی یک سری قوانین سراسری نیز وجود خواهد داشت که مربوط به کل پایگاه داده توزیع شده می‌باشد. بعنوان مثال سیستم در یکی سیستم دانشگاهی که در شهر‌های مختلفی توزیع شده است، ممکن است بخواهیم تعداد کل دانشجویان ثبت نام شده در سیستم از هزار نفر بیشتر نباشد. عموما درچنین سیستم هایی یک DBMS مدیریت کننده نیز وجود دارد که مسئول برقراری هماهنگی بین سایر DBMS‌ها و نیز اعمال اینگونه قوانین جامعیتی سراسری می‌باشد.  
تراکنش‌های توزیع شده یک یا چند تراکنش جزئی تشکیل شده اند که ممکن است هریک از آنها مربوط به یکی از DBMS‌های سیستم باشد. چنین تراکنش هایی معمولا ابتدا توسط سیستم مدیریتی مرکزی دریافت می‌شوند و سپس هرکدام از پرس و جو‌های داخلی آن به DBMS مربوطه ارسال می‌گردد. اجرای هرکدام از پرس و جو‌های جزئی (که خود می‌توانند تراکنشی مستقل نیر باشند) بطور مستقل و محلی بر روی ماشین مربوطه اجرا شده و در انتها نیز نتیجه اجرا به سیستم مدیریتی باز گردانده می‌شود. سیستم مدیریتی مرکزی منتظر می‌ماند که تمامی تراکنش‌ها اعلام COMMIT کنند تا از انجام موفقیت آمیز همه انها اطمینان حاصل نماید. پس از کسب اطمینان کل تراکنش توسط این سیستم مرکزی COMMIT شده و در نتیجه تغییرات بر روی پایگاه داده توزیه شده اعمال می‌شوند. به این سیاست COMMIT کردن، کامیت دو مرحله ای یا Two-phase Commit گفته می‌شود. توجه داشته باشید که در صورتی که هریک از DBMS‌ها اعلام شکست نمایند تمامی تراکنش توزیع شده ROLLBACK می‌گردد.  
tx_begin();
            execute T1  //at site D
            execute T2  //at site C
            Execute T3  //at site B
            …
tX_commit ();
همانطور که در مثال بالا مشاهده می‌کنید تراکنش اصلی از سه تراکنش T1، T2 و T3 تشکیل شده که مر بوط به سه سایت متفاوت می‌باشند. در زمانی تراکنش اصلی COMMIT خواهد شد که هر سه سایت اعلام موفقیت کنند.
 
تراکنش‌های تو در تو (Nested Transaction):
این نوع از تراکنش نسبت به دو نوع تراکنش قبلی پیچیدگی بیشتری به لحاظ پیاده سازی و مدیریت دارند. این گونه تراکنش‌ها عموما واحد‌های کاری بزرگی هستند که در داخل آنها درختی از تراکنش‌های تو در تو را داریم که مجموعه تمامی انها در نهایت یک کار واحد بلحاظ منطقی را انجام می‌دهند. هر یک از تراکنش‌های داخلی بعنوان یک گره در این ساختار درختی قرار دارند که می‌توانند پدر و یا فرزندانی داشته باشند.
 
در تراکنش‌های تو در تو شرایطی حاکم است.
هر گره در ساختار درختی تراکنش تنها قادر به دیدن برادر‌های خود می‌باشد. به بیان دیگر فرزندان برادران خود را نمی‌بیند و نسبت به انها هیچ اطلاعی ندارد. 
در تراکنش‌های تو در تو امکان اجرای موازی فرزندان یک گره وجود دارد.
امکان اجرای موازی تراکنش‌ها منجر می‌شود به این که تراکنش‌های داخلی قادر به دیدن خروجی حاصل از اجرا همدیگر نباشند.
هر تراکنشی به طور مستقل ویژگی atomicity را دارد اما پایداری (durability) و کامیت شدن آنها وابسته به پدرانشان می‌باشد.
در صورتی که پدری تصمیم بگیرد می‌تواند تمامی زیر تراکنش هایش را خاتمه (abort) دهد.
در تراکنش‌های موازی COMMIT شدن یک گره پدر به دو صورت امکان پذیر است. 
 
حالت AND: در این حالت یک تراکنش در صورتی کامیت خواهد شده که تمامی فرزندان آن با موفقیت اجرا و COMMIT شده باشند.
حالت OR: در این حالت اگر حتی یکی از تراکنش‌های فرزند نیز موفق به COMMIT شده باشد تراکنش پدر نیز COMMIT خواهد شد.
 
تراکنش‌های چند سطحی (Multi-level Transactions) :
این نوع نیز همانند تراکنش‌های تو در تو پیچیده است. از نظر ساختاری تراکنش‌های چند سطحی مشابه تراکنش‌های تو در تو می‌باشند ولی به لحاظ مفهومی با یکدیگر متفاوت هستند. اولین تفاوت موجود بین این دو نوع اینست که هر زیر تراکنشی قادر است خروجی زیر تراکنش‌های دیگر را ببیند. این مسئله باعث می‌شود که تنوانیم زیر تراکنش‌ها را بصورت همروند و موازی اجرا کنیم که این دومین تفاوت مفهومی بین این دو می‌باشد. هنگامی که زیر تراکنش کامل شد (COMMIT) تمامی قفل‌های مربوط به خود را آزاد می‌کند که این مورد نیز در مورد تراکنش‌های تو در تو صادق نمی‌باشد. یکی از مهمترین تفاوت‌های دیگر بین این دو نوع در اینست که در تراکنش‌های چند سطحی تمامی برگ‌ها در یک سطح از درخت قرار دارند و تنها تراکنش‌های برگ هستند که مستقیما به پایگاه داده مراجعه می‌کنند. در مورد کایت شدن نیز شروط مربوط به تراکنش‌های تو در تو در اینجا وجود ندارند و زیر تراکنش‌ها می‌توانند بدون هیچ شرطی کامیت شوند.
 
تراکنش‌های زنجیره ای (Chained Transaction):
همانطور که از نام این نوع از تراکنش‌ها پیداست، این تراکنش‌ها از زنجیره ای از زیر تراکنش‌های پی در پی تشکیل شده اند. تا زمانی که تمامی حلقه‌های این زنجیر با موفقیت اجرا نشوند سیستم به حالت سازگاری نخواهد نرفت. دراین نوع از تراکنش‌های COMMIT هر حلقه باعث پایداری شدن (durable) داده‌های در پایگاه داده خواهد شد. این مسئله ممکن است پایگاه داده را به وضعیت ناسازگاری ببرد. در هنگام کامیت شدن هر حلقه قفل‌های مربوط به آن نیز آزاد می‌شود.
 
حلقه‌های مختلف زنجیره تراکنشی می‌توانند با یکدیگر تبادل اطلاعات کنند. البته توجه داشته باشید که منابعی که هر کدام از آنها بر روی آن کار می‌کنند با دیگری متفاوت می‌باشد. بعنوان نمونه تراکنشی را نظر بگیرد که قصد دارد متوسط مبلغ مکالمه تلفن همراه مشترکان یک مخابرات را محاسبه کند. بدلیل تعداد بالای مشترکان ممکن است این تراکنش را در قالب یک تراکنش زنجیره ای پیاده سازی کنیم که هر حلقه از آن مسئول محاسبه این مبلغ برای ده هزار نفر از کاربران باشد. توجه داشته باشید که برای بدست آوردن مقدار متوسط نیاز داریم که هر زیر تراکنش‌ها قادر به تبادل اطلاعات باشند. از طرفی منابع مورد استفاده آنها (رکورد ها) با یکدیگر متفاوت خواهد بود و نمی‌توانند تغییرات یکدیگر را ببینند. سوالی که مطرح می‌شود اینست که مبادله اطلاعات بین حلقه‌های تراکنش به چه صورت باید انجام شود؟ در جواب این سوال باید گفت که مبادله اطلاعات بین تراکنش‌ها از طریق متغیر‌های رابطه ای که هما متغیر‌های پایگاه داده هستند انجام می‌گیرد.
 
 
SavePoint:
در برخی شرایط ممکن است بخواهیم در هنگام ROLLBACK مجددا به ابتدای تراکنش باز نگردیم تا مجبور باشیم دوباره کار را از ابتدا از سر بگیریم. بعنوان مثال تا قسمتی از تراکنش پیش رفتیم، به خطایی بر خورد می‌کنیم و می‌خواهیم از نقطه ای خاص از تراکنش کا را از سر بگیریم. در چنین کاربرد هایی از ابزاری بنام SavePoint استفاده می‌کنم.
 
برای روشن‌تر شدن مفهوم SavePoint فرض کنید قصد داریم بلیطی از تهران به سیدنی رزرو کنیم. برای این منظور ابتدا عمل رزرواسیون را از تهران به دوبی انجام می‌دهیم و سپس از دوبی به سنگاپور و در نهایت از سنگاپور به سیدنی. حال در این بین می‌توانیم در نقطه تهران – دوبی SavePoint قرار دهیم تا در صورت بروز هرگونه خطا مجددا رزرواسیون را از ابتدا آغاز نکنیم. اگر در هنگام رزرو بلیط دوبی – سنگاپور خطایی بروز دهد می‌توانیم به نقطه تهران – دوبی ROLLBACK کنیم و از آنجا مسیر دیگری را انتخاب کنیم. توجه داشته باشید که ROLLBACK به SavePoint وضعیت پایگاه داده به همان نقطه بازگردانده می‌شود. 
begin transaction();
            s1;
            sp1:= create savepoint(0);
            s2;
            sp2:= create savepoint(0);
            if (condition)
            rollback (spi);
            …
            …
            commit
Auto Transaction:
این قبیل تراکنش‌ها تراکنش‌های کوچکی هستند  که توسط سیستم تعریف می‌شوند. بعنوان مثال سیستم برای انجام دستورات زیر تراکنش تعریف می‌کند :
Alter table, Create, delete, insert, open, drop, fetch, grant, revoke, select, truncate table, update
یکی از علت‌های این امر اینست که در صورت بروز خطا در حین این تراکنش‌های خود کار امکان اجرای مجدد هر کدام فراهم گردد.
 
شروع تراکنش‌ها :
همانطور که گفته شد برای شروع تراکنش‌ها می‌توانیم صراحتا از BEGIN TRANSACTION استفاده کنیم. البته راهکار دیگری نیز وجود دارد که در آن می‌توانیم به DBMS اعلام کنیم که با پایان یک تراکنش پیش از شروع تراکنش بعدی BEGIN TRANSACTION را قرار بده. برای این منظور از دستور زیر استفاده می‌کنیم :
Set implicit_transaction on
برخی از ویژگی‌های تراکنش‌ها را می‌توان تغییر داد. بعنوان مثال می‌توان گفت که تراکنش جاری تنها اجازه خواندن از پایگاه داده را دارد. در این حالت از دستور زیر می‌توان استفاده نمود : 
SET TRANSACTION READ ONLY
همچنین میتوان اجازه تغییر را  به آن داد :
SET TRANSACTION READ WRITE
علاوه بر موارد بالا می‌توان سطح ایزولاسیون تراکنش را با دستود SET تغییر داد. این سطوح در زیر آورده شده اند که بحث در مورد آنها را به مقاله دیگر در مقوله همروندی موکول می‌کنیم. 
READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE
موفق و پیروز باشید
نظرات نظرسنجی‌ها
در محیط برنامه نویسی از دارک مود استفاده می کنید یا لایت مود؟
درود به همه دوستان و با احترام به همه نظرات
بنده تقریبا از زمانی که dark mode در دسترس قرار گرفت از این حالت تیره استفاده میکنم ، خوب قبلا از محیط روشن light mode استفاده میکردم تجربیاتی که داشتم رو ذکر میکنم :
  1. به دلیل کار بیش از 10 ساعت روزانه ، با توجه به اینکه مشکل بینایی نداشتم ولی حالت روشن باعث عصبی بودن و بیخوابی مزمن شده بود با تغییر محیط به حالت تیره تاثیر بسیار زیادی در کیفیت خواب داشتم بصورتی که این موضوع کاملا محسوس بود.
  2. از طرفی کار با 2 یا 3 مانیتور با حالت روشن ، نیاز به دقت بیشتری دارد و خستگی زیادی رو به چشم تحمیل میکند و مدت زمان کمتری با دقت بالا میتونستم کار کنم و تمرکزم به دلیل صفحه سفید کمتر بود.
  3. اگر محیط نور مناسب و ملایمی داشته باشد و از پشت سر باشد حالت روشن خستگی کمتری خواهد داشت و چشم رو کمتر اذیت میکنه ولی در حالت تیره خستگی چشم خیلی کمتر خواهد بود و تداخل رنگی کمتری داریم.
  4. برای برنامه نویسی بلند مدت ، حالت تیره و برای طراحی گرافیک و کار با تصاویر حالت روشن (به دلیل وضوح مناسب ) بیشتر توصیه میکنم .
مشاغل مشابه برنامه نویسی و کار با کامپیوتر به دلیل عدم تحرک کافی بدن و پشت میز نشینی آسیبهای زیادی را وارد میکند اما در هر صورت به نظرم هر کسی قبل از انتخاب محیط کاری خود باید با یک چشم پزشک آشنا به تکنولوژی و شغل مورد نظر ، مشاوره کند تا بتواند از محیط شغلی خودش کمتر آسیب ببیند.

نظرات مطالب
روش استفاده‌ی صحیح از HttpClient در برنامه‌های دات نت
پروژ ه ام از نوع asp.net core 2.1 است.
در لایه WebApp مشکلی ندارم و در کلاس Startup آن را فراخوانی کرده ام و به خوبی کار می‌کند.
لایه سرویسم از نوع .Net Standard می‌باشد می‌خواهم این کتابخانه را در لایه سرویس استفاده کنم
نظرات مطالب
نوشتن TagHelperهای سفارشی برای ASP.NET Core
من در حین ایجاد tag helper سفارشی برای منو‌ها به مشکلی برخوردم
برای ایجاد لینک‌های صفحه از url.Action  به صورت زیر استفاده میکنم: 
  Menu.ChildsList.Add(new ChildMenu()
                {
                    Text = "داشبورد",
                    Url = url.Action(new UrlActionContext() { Action = "Index", Controller = "Home"})
                });
 اما در کلاس UrlActionContext پارامتری برای مشخص کردن Area وجود نداره! 
مطالب
چک لیست تهیه یک گزارش خوب

مشخصات یک گزارش خوب عموما به شرح زیر است:

1- باید هر سطر گزارش شماره ردیف داشته باشد. (باید امکان ارجاع به هر سطر در صورت بروز مشکل میسر باشد)
2- باید در هر صفحه، شماره صفحه و تعداد کل صفحات ذکر شود. (اگر چاپ شد بر این اساس بتوان ارتباط بین صفحات را یافت)
3- در هر صفحه باید تاریخ و ساعت روز تهیه گزارش حتما ذکر شود. (بعدا جهت رفع اختلافات لازم می‌شود. مثلا می‌گویند این عدد اشتباه است. اما واقعا این عدد در زمان تهیه گزارش درست بوده، اما الان بر اساس اطلاعات جدید ... بله ... چیزی دیگری است، یا به قول آن‌ها اشتباه است)
4- در پایان هر صفحه، یک سری از ستون‌های عددی باید جمع کل داشته باشد.
5- در ابتدای هر صفحه باید "نقل از صفحه قبل" یا همان سطر جمع کل صفحه قبل ذکر شود.
6- هدر گزارش باید در تمام صفحات تکرار شود. (باید مشخص باشد این صفحه گزارش که الان به دست من رسیده متعلق به کجاست، عنوانش چیست حداقل؟)
7- سر ستون‌ها هم باید در هر صفحه تکرار شوند. (مثلا الان صفحه 20 یک گزارش پیش روی شما است. باید بدانید معنای این ستون سوم ظاهر شده در گزارش چیست)
8- تمام اعداد موجود در گزارش باید جداکننده سه رقمی داشته باشند. (خواندن 4446327531 ساده‌تر است یا خواندن 4,446,327,531 ؟)
9- تمام اعداد گزارش باید فارسی نمایش داده شوند. (این مورد را می‌شود با فونت‌های دستکاری شده که احتمالا شما هم یک دوجین از آن‌ها را دارید، حل کرد. فونت‌هایی که با یک فونت ادیتور مثل برنامه معروف FontCreator ویرایش شده و بجای اعداد انگلیسی آن‌ها، همان اعداد فارسی قرار گرفته‌اند)