نظرات مطالب
شروع به کار با EF Core 1.0 - قسمت 8 - بررسی رابطه‌ی Many-to-Many
لیست صفحه بندی شده‌ی تگ‌های مطلب اول
var post1Tags = context.BlogPosts
      .Where(blogPosts => blogPosts.Id == 1)
      .SelectMany(blogPosts => blogPosts.BlogPostsJoinTags)
      .Select(blogPostsJoinTags => blogPostsJoinTags.Tag)
      .Skip(0)
      .Take(10)
      .ToList();
با این خروجی SQL
SELECT   [blogPosts.BlogPostsJoinTags.Tag].[Id],
         [blogPosts.BlogPostsJoinTags.Tag].[Name]
FROM     [BlogPosts] AS [blogPosts]
         INNER JOIN
         [BlogPostsJoinTags] AS [blogPosts.BlogPostsJoinTags]
         ON [blogPosts].[Id] = [blogPosts.BlogPostsJoinTags].[BlogPostId]
         INNER JOIN
         [Tags] AS [blogPosts.BlogPostsJoinTags.Tag]
         ON [blogPosts.BlogPostsJoinTags].[TagId] = [blogPosts.BlogPostsJoinTags.Tag].[Id]
WHERE    [blogPosts].[Id] = 1
ORDER BY @@ROWCOUNT
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY;
مطالب دوره‌ها
استفاده از Adobe iFilter برای جستجوی Full Text در فایل‌های PDF
در قسمت‌های قبل، نحوه‌ی کار با فیلترهای FTS آفیس را بررسی کردیم. شرکت Adobe نیز برای جستجوی Full-Text بر روی فایل‌های PDF، یک iFilter خاص را طراحی کرده‌است که نسخه‌ی آخر آن‌را از آدرس ذیل می‌توانید دریافت کنید:
یک تجربه‌ی مهم: نگارش 11 آن را با SQL Server X64 تست کردم کار نکرد. اما نگارش 9 کار می‌کند.
مستندات کامل


پس از نصب ابتدایی آن، مراحل ذیل را برای فعال سازی آن باید طی کرد:

1) تنظیم مسیر پوشه bin نصب فیلتر (مهم!)
 Start > Control Panel > System > Advanced
Environment Variables -> System Variables -> find PATH
مسیر فوق را در تنظیمات ویندوز یافته و سپس به انتهای Path، آدرس پوشه bin فیلتر نصب شده را اضافه کنید:
 C:\Program Files\Adobe\Adobe PDF iFilter 9 for 64-bit platforms\bin\
دقت داشته باشید که این مسیر باید به \ ختم شود.
سپس کل سیستم را ری استارت کنید.


2) ثبت آن در وهله‌ی جاری SQL Server
برای این منظور ابتدا دستورات ذیل را جرا کنید:
 exec sys.sp_fulltext_service 'load_os_resources', 1;
EXEC sp_fulltext_service 'verify_signature', 0
EXEC sp_fulltext_service 'update_languages'; -- update language list
EXEC sp_fulltext_service 'restart_all_fdhosts'; -- restart daemon
reconfigure with override
گزینه‌ی verify_signature مربوط به فایل‌های iFilter ایی است که امضای دیجیتال ندارند.
سپس در management studio یکبار بر روی وهله‌ی جاری کلیک راست کرده و گزینه‌ی Restart را انتخاب کنید (مهم).

3) پس از ری‌استارت SQL Server، اطمینان حاصل کنید که این فیلتر جدید نصب شده‌است:
 exec sys.sp_help_fulltext_system_components 'filter';


و یا کوئری ذیل نیز برای این منظور مفید است:
 SELECT document_type, path from sys.fulltext_document_types where document_type = '.pdf'

4) در ادامه برای استفاده از آن آزمایش ذیل را ترتیب خواهیم داد.

ایجاد یک جدول جدید که فایل‌های باینری PDF را در خود ذخیره می‌کند:
 CREATE TABLE PdfDocuments
(
id INT IDENTITY(1,1) NOT NULL,
doctype NCHAR(4) NOT NULL,
doccontent VARBINARY(MAX) NOT NULL,
CONSTRAINT PK_PdfDocuments
PRIMARY KEY CLUSTERED(id)
);
ستون‌های doctype معرف نوع سند و doccontent ذخیره کننده‌ی محتوای کامل فایل‌های PDF خواهند بود.
سپس چند رکورد را در آن ثبت می‌کنیم. برای نمونه دو مقاله‌ی خروجی PDF سایت جاری را در این جدول ثبت خواهیم کرد:
 INSERT INTO PdfDocuments(doctype, doccontent)
SELECT
N'PDF',
bulkcolumn FROM OPENROWSET (BULK 'C:\Users\Vahid\Downloads\1732-DotNetTips.pdf', SINGLE_BLOB) AS doc;

INSERT INTO PdfDocuments(doctype, doccontent)
SELECT
N'PDF',
bulkcolumn FROM OPENROWSET (BULK 'C:\Users\Vahid\Downloads\1733-DotNetTips.pdf', SINGLE_BLOB) AS doc;
در ادامه علاقمندیم تا بر روی خواص و متادیتای فایل‌های PDF نیز بتوانیم جستجوی FTS انجام دهیم. به همین منظور search propery list متناظری را نیز تعریف خواهیم کرد. همانطور که در قسمت‌های قبل عنوان شد، نیاز است GUID هر خاصیت را برای تعریف از سازنده‌ی iFilter دریافت کرد. این اطلاعات در سند ذیل مستند شده‌اند:

 -- Search property list
CREATE SEARCH PROPERTY LIST PdfSearchPropertyList;
GO
ALTER SEARCH PROPERTY LIST PdfSearchPropertyList
ADD 'Author'
WITH (PROPERTY_SET_GUID = 'F29F85E0-4FF9-1068-AB91-08002B27B3D9',
PROPERTY_INT_ID = 4,
PROPERTY_DESCRIPTION = 'Author - author of a given item.');
GO

در اینجا اگر علاقمند بودید، stop list معرفی شده در قسمت‌های قبل را نیز می‌توان افزود.
 CREATE FULLTEXT STOPLIST SQLStopList;
GO
-- Add a stopwords
ALTER FULLTEXT STOPLIST SQLStopList ADD N'به' LANGUAGE 'English';
ALTER FULLTEXT STOPLIST SQLStopList ADD N'با' LANGUAGE 'English';
--.....

سپس یک کاتالوگ FTS و ایندکس Full-Text ایی را بر روی این جدول ایجاد می‌کنیم:
 -- Full-text catalog
CREATE FULLTEXT CATALOG PdfDocumentsFtCatalog;
GO

-- Full-text index
CREATE FULLTEXT INDEX ON PdfDocuments
(
  [doccontent] TYPE COLUMN [doctype]
  Language 1033
  STATISTICAL_SEMANTICS
)
KEY INDEX PK_PdfDocuments
ON PdfDocumentsFtCatalog
WITH STOPLIST = SQLStopList,
  SEARCH PROPERTY LIST = PdfSearchPropertyList,
  CHANGE_TRACKING AUTO;
GO

آیا کار می‌کند ؟ چیزی ایندکس شده‌است؟
 SELECT
 I.document_id,
 I.display_term,
 I.occurrence_count
FROM sys.dm_fts_index_keywords_by_document(DB_ID(DB_NAME()), OBJECT_ID(N'dbo.PdfDocuments')) AS I
INNER JOIN dbo.PdfDocuments D
ON D.id = I.document_id;


انجام دو کوئری بر روی آن. یکی برای یافتن متنی ساده و دیگری برای یافتن خواص

 SELECT *
FROM PdfDocuments
WHERE CONTAINS(doccontent, N'است')

SELECT
 I.document_id,
 I.display_term,
 I.property_id
FROM sys.dm_fts_index_keywords_by_property(DB_ID(DB_NAME()), OBJECT_ID(N'dbo.PdfDocuments')) AS I
INNER JOIN dbo.PdfDocuments D
ON D.id = I.document_id;


 
پاسخ به پرسش‌ها
آیا امکان استفاده از Extension Method در زمان Select وجود دارد؟

البته یک نمونه در اینترنت پیدا کردم (البته پاسخ Copilot بوده) که متد را بصورت Generic تعریف کرده بود که برای انجام Dynamic Select روش زیر را بکاربرده بود:

IQueryable<TResult> results = query.SelectMany(x => selectProperties.Select(prop => prop.Compile()(x)));

تا اینجا هیچ مشکلی وجود ندارد ولی به محض آنکه در خط بعدی متد ToList اجرا میشه با پیغام خطا مواجه میشم:

An exception was thrown while attempting to evaluate a LINQ query parameter expression. See the inner exception for more information. To show additional information call 'DbContextOptionsBuilder.EnableSensitiveDataLogging'.

کد کامل Copilot:

public async Task<List<LineJoint2>> GetAsync2(
    Expression<Func<LineJoint, bool>> filter,
    List<Expression<Func<LineJoint, object>>> includes,
    List<Func<IIncludableQueryable<LineJoint, object>, IIncludableQueryable<LineJoint, object>>> thenIncludes,
    Expression<Func<IQueryable<LineJoint>, IOrderedQueryable<LineJoint>>> orderBy,
    int pageSize,
    int pageNumber,
    bool trackChanges = true,
    CancellationToken cancellationToken = default)
{
    var query = context.LineJoints.AsQueryable();

    // Apply filter
    if (filter != null)
        query = query.Where(filter);

    // Include related entities
    foreach (var include in includes)
        query = query.Include(include);

    // Apply thenIncludes
    foreach (var thenInclude in thenIncludes)
        query = thenInclude(query);

    // Project properties dynamically
    var projectedQuery = query.Select(x => new LineJoint2
    {
        Id = x.Id,
        JointNo = x.JointNo
        // Add other properties from LineJoint as needed
    });

    // Apply ordering
    if (orderBy != null)
        projectedQuery = orderBy.Compile()(projectedQuery);

    // Apply pagination
    var pagedQuery = projectedQuery.Skip((pageNumber - 1) * pageSize).Take(pageSize);

    // Execute the query
    return await (trackChanges ? pagedQuery : pagedQuery.AsNoTracking()).ToListAsync(cancellationToken);
}
مطالب
چگونه کدها را مستند سازی کنیم؟
یکی از مهمترین مسائل، به خصوص در کارهای تیمی یا پروژه‌های اشتراکی، قرار دادن کامنت‌ها یا اصطلاحا مستند نویسی است که بسیاری از برنامه نویسان با اینکه نظریه آن‌را به شدت قبول دارند، ولی از انجام آن سرباز می‌زنند که به دو عامل تنبلی و عدم دانش نحوه‌ی مستند نویسی بر می‌گردد. در این مقاله قصد داریم به سوالات زیر پاسخ دهیم:
  • چرا به کامنت گذاری یا مستند نویسی نیاز داریم؟
  • چگونه کامنت بنویسیم؟
  • انواع کامنت‌ها چیست؟
  • چه کامنت‌هایی اشتباه هستند؟

همانطور که بیان کردیم، کامنت گذاری یکی از مهم‌ترین کارهایی است که یک برنامه نویس انجام می‌دهد. به خصوص زمانیکه به صورت تیمی کار می‌کنید، این امر مهم‌تر از قبل خود را نشان می‌دهد. بسیاری از برنامه نویسان که بیشتر دلیل آن تنبلی است، از این کار سرباز می‌زنند و ممکن است آن را اتلاف وقت بدانند. ولی با کامنت گذاری فهم و درک کد، در آینده بالا‌تر می‌رود. در مقاله‌ی تخصصی «هنر کامنت نویسی» نوشته‌ی «برنهارد اسپویدا» بهانه‌های جالبی از برنامه نویسان را برای سرباز زدن از اینکار، ذکر شده است؛ به عنوان نمونه:
من کدم را به خوبی متوجه می‌شوم.
کد خوب، خودش گویای همه چیز هست.
وقتی برای کامنت نویسی وجود ندارد. باید چسبید به کد.


سوالات زیر نیز دلیل این را که چرا باید کامنت گذاری کرد، مشخص می‌کنند:
  • شاید امروز معنای یک کد را متوجه شوید، ولی آیا در آینده، مثلا یک سال بعد هم چنین خواهد بود؟
  •  آیا می‌توانید هر سیستمی را که طراحی می‌کنید، به خاطر بسپارید که فعالیت‌هایش را به چه نحوی انجام می‌دهد؟
  • اگر در یک کار تیمی باشید، شاید شما متوجه کدتان می‌شوید، ولی آیا تضمینی وجود دارد که دیگران هم متوجه روش شما شوند؟
  • آیا کدی که شما بر روی آن فکر کرده‌اید و در ذهن خود روش انجام آن را ترسیم کرده‌اید، می‌تواند برای برنامه نویسی که کد شما را می‌بیند هم رخ دهد؟ 
  • اگر شما به صورت تیمی کاری را انجام دهید و یکی از برنامه نویس‌های شما از تیم جدا شود، چگونه می‌توانید کار او را دنبال کنید؟
  • اگر برای برنامه نویسی اتفاق یا حادثه‌ای پیش بیاید که دسترسی شما به او ممکن نباشد چه؟
کدی که مستند نشود، یا خوب مستند نشود، در اولین مرحله وقت شما یا هر فردی را که روی این کد کار می‌کند، برای مدتی طولانی می‌گیرد. در مرحله‌ی بعدی احتمالا مجبور هستید، کد را خط به خط دنبال کرده تا تاثیر آن را بر ورودی‌ها و خروجی‌ها ببینید. تمام این‌ها باعث هدر رفتن وقت شما شده و ممکن است این اتفاق برای هر تکه کدی رخ بدهد.


سطوح کامنت نویسی بر سه نوع هستند:

Documentary Comments:
این مستند سازی در سطح یک سند مثل فایل یا به خصوص یک پروژه رخ می‌دهد که شامل اطلاعات و تاریخچه‌ی آن سند است که این اطلاعات به شرح زیر هستند:

 File Name   نام سند
 File Number/Version Number   شماره نسخه آن سند
 Creation Date   تاریخ ایجاد آن
 Last Modification Date
 تاریخ آخرین تغییر سند
 Author's Name
 سازنده‌ی سند
 Copyright Notice
 اطلاعاتی در مورد کپی رایت سند
 Purpose Of Program
 هدف کاری برنامه. یک خلاصه از آن چه برنامه انجام می‌دهد.
 Change History
 لیستی از تغییرات مهمی که در جریان ایجاد آن رخ داده است.
 Dependencies  وابستگی‌های سند. بیشتر در سطح پروژه معنا پیدا می‌کند؛ مانند نمونه‌ی آن برای سایت جاری که به صورت عمومی منتشر شده است.
 Special Hardware Requirements
 سخت افزار مورد نیاز برای اجرای برنامه. حتی قسمتی می‌تواند شامل نیازمندی‌های نرم افزاری هم باشد.
نمونه ای از این مستند سازی برای برنامه ای که به زبان پاسکال نوشته شده است:
PCMBOAT5.PAS*************************************************************
**
File: PCMBOAT5.PAS
Author: B. Spuida
Date: 1.5.1999
Revision: 
1.1 
PCM-DAS08 and -16S/12 are supported.
Sorting routine inserted.
Set-files are read in and card as well as
amplification factor are parsed.

1.1.1
Standard deviation is calculated.

1.1.2
Median is output. Modal value is output.

1.1.4
Sign in Set-file is evaluated.
Individual values are no longer output.
(For tests with raw data use PCMRAW.EXE)

To do:
outliers routine to be revised.
Statistics routines need reworking.
Existing Datafile is backed up.

Purpose: 
Used for measurement of profiles using the
Water-SP-probes using the amplifier andthe PCM-DAS08-card, values are acquired
with n = 3000. Measurements are taken in 1
second intervals. The values are sorted using
Quicksort and are stacked "raw" as well as after
dismissing the highest and lowest 200 values as
'outliers'.


Requirements:
The Card must have an A/D-converter.
Amplifier and probes must be connected.
Analog Signal must be present.
CB.CFG must be in the directory specified by the
env-Variable "CBDIREC" or in present directory.

در بالا، خصوصیت کپی رایت حذف شده است. دلیل این امر این است که این برنامه برای استفاده در سطح داخلی یک شرکت استفاده می‌شود.


Functional Comments: کامنت نویسی در سطح کاربردی به این معنی نیست که شما اتفاقاتی را که در یک متد یا کلاس یا هر بخشی روی می‌دهد، خط به خط توضیح دهید؛ بلکه چرخه‌ی کاری آن شی را هم توضیح بدهید کفایت می‌کند. این مورد می‌تواند شامل این موارد باشد:
  • توضیحی در مورد باگ‌های این قسمت
  • یادداشت گذاری برای دیگر افراد تیم
  • احتمالاتی که برای بهبود ویژگی‌ها و کارایی کد وجود دارد.


Explanatory Comment: کامنت گذاری توصیفی در سطح کدنویسی رخ می‌دهد و شامل توضیح در مورد کارکرد یک شیء و توضیح کدهای شیء مربوطه می‌گردد. برای قرار دادن کامنت الزامی نیست که کدها را خط به خط توضیح دهید یا اینکه خطوط ساده را هم تشریح کنید؛ بلکه کامنت شما همینقدر که بتواند نحوه‌ی کارکرد هر چند خط کد مرتبط به هم را هم توضیح دهد، کافی است. این توضیح‌ها بیشتر شامل موارد زیر می‌شوند:

  • کدهای آغازین
  • کدهای خروجی
  • توضیح کوتاه از آنچه که این شیء ، متد یا ... انجام می‌دهد. 
  • حلقه‌های طولانی یا پیچیده
  • کدهای منطقی عجیب و پیچیده
  • Regular Expression

کدهای آغازین شروع خوبی برای تمرین خواهند بود. به عنوان نمونه اینکه توضیحی در مورد ورودی و خروجی یک متد بدهید که آرگومان‌های ورودی چه چیزهایی هستند و چه کاربری داردند و در آغاز برنامه، برنامه چگونه آماده سازی و اجرا می‌شود. مقادیر پیش فرض چه چیزهایی هستند و پروژه چگونه تنظیم و مقداردهی می‌شود.

کدهای خروجی هم به همین منوال است. خروجی‌های نرمال و غیرنرمال آن چیست؟ کدهای خطایی که ممکن است برگرداند و ... که باید به درستی توضیح داده شوند.

توضیح اشیاء و متدها و ... شامل مواردی چون: هدف از ایجاد آن، آرگومان هایی که به آن پاس می‌شوند و خروجی که می‌دهد و اینکه قالب یا فرمت آن‌ها چگونه است و چه محدودیت‌هایی در مقادیر قابل انتظار وجود دارند. ذکر محدودیت‌ها، مورد بسیاری مهمی است و دلیل بسیاری از باگ‌ها، عدم توجه یا اطلاع نداشتن از وجود این محدودیت هاست. مثلا محدوده‌ی خاصی برای آرگومان‌های ورودی وجود دارد؟ چه اتفاقی می‌افتد اگر به یک بافر 128 کاراکتری، 1024 کاراکتر را ارسال کنیم؟

کدهای منطقی عجیب، یکی از حیاتی‌ترین بخش‌های کامنت گذاری برای نگه داری یک برنامه در آینده است. به عنوان نمونه استفاده از عبارات با قاعده، اغلب اوقات باعث سردرگمی کاربران شده است. پس توضیح دادن در مورد این نوع کدها، توصیه زیادی می‌شود. اگر عبارات با قاعده شما طولانی هستند، سعی کنید از هم جدایشان کنید یا خطوط آن را بشکنید و هر خط آن را توضیح دهید.

سیستم کامنت گذاری
هر زبانی از یک سیستم خاص برای کامنت گذاری استفاده می‌کند. به عنوان مثال پرل از سیستم (POD (Plain Old Documentation استفاده می‌کند یا برای Java سیستم JavaDoc یا برای PHP از سیستم PHPDoc  (+ ) که پیاده سازی از JavaDoc می‌باشد استفاده می‌کنند. این سیستم برای سی شارپ استفاده از قالب XML است. کد زیر نمونه‌ای از استفاده از این سیستم است:
// XMLsample.cs
// compile with: /doc:XMLsample.xml
using System;
/// <summary>
/// Class level summary documentation goes here.</summary>
/// <remarks>
/// Longer comments can be associated with a type or member
/// through the remarks tag</remarks>
public class SomeClass
{
    /// <summary>
    /// Store for the name property</summary>
    private string myName = null;

    /// <summary>
    /// The class constructor. </summary>
    public SomeClass()
    {
        // TODO: Add Constructor Logic here
    }

    /// <summary>
    /// Name property </summary>
    /// <value>
    /// A value tag is used to describe the property value</value>
    public string Name
    {
        get
        {
            if (myName == null)
            {
                throw new Exception("Name is null");
            }
            return myName;
        }
    }

    /// <summary>
    /// Description for SomeMethod.</summary>
    /// <param name="s"> Parameter description for s goes here</param>
    /// <seealso cref="String">
    /// You can use the cref attribute on any tag to reference a type or member
    /// and the compiler will check that the reference exists. </seealso>
    public void SomeMethod(string s)
    {
    }
}

دستورات سیستم کامنت گذاری سی شارپ

در سایت جاری، دو مقاله زیر اطلاعاتی در رابطه با نحوه‌ی کامنت گذاری ارئه داده‌اند.
- در مقاله «زیباتر کد بنویسیم» چند مورد آن به این موضوع اختصاص دارد.
- مقاله «وادار کردن خود به کامنت نوشتن» گزینه‌ی کامنت گذاری اجباری در ویژوال استودیو را معرفی می‌کند.
مطالب
آشنایی با NHibernate - قسمت نهم

استفاده از Log4Net جهت ثبت خروجی‌های SQL حاصل از NHibernate

هنگام استفاده از NHibernate، پس از افزودن ارجاعات لازم به اسمبلی‌های مورد نیاز آن به برنامه، یکی از اسمبلی‌هایی که به پوشه build برنامه به صورت خودکار کپی می‌شود، فایل log4net.dll است (حتی اگر ارجاعی را به آن اضافه نکرده باشیم) که جهت ثبت وقایع مرتبط با NHibernate مورد استفاده قرار می‌گیرد. خوب اگر مجبوریم که این وابستگی کتابخانه NHibernate را نیز در پروژه‌های خود داشته باشیم، چرا از آن استفاده نکنیم؟!
شرح مفصل استفاده از این کتابخانه سورس باز را در سایت اصلی آن می‌توان مشاهده کرد:


برای اینکه از این کتابخانه در برنامه خود جهت ثبت عبارات SQL تولیدی توسط NHibernate استفاده کنیم، باید مراحل زیر طی شوند:
الف) ارجاعی را به اسمبلی log4net.dll اضافه نمائید (کنار اسمبلی NHibernate در پوشه build برنامه باید موجود باشد)
ب) فایل app.config برنامه را (برنامه ویندوزی) به صورت زیر ویرایش کرده و چند سطر مربوطه را اضافه نمائید (در مورد برنامه‌های وب هم به همین شکل است. configSections فایل web.config تنظیم شده و سپس تنظیمات log4net را قبل از بسته شدن تگ configuration اضافه نمائید ) :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>

<connectionStrings>
<!--NHSessionManager-->
<add name="DbConnectionString"
connectionString="Data Source=(local);Initial Catalog=HelloNHibernate;Integrated Security = true"/>
</connectionStrings>

<log4net>
<appender name="rollingFile"
type="log4net.Appender.RollingFileAppender,log4net" >
<param name="File" value="NHibernate_Log.txt" />
<param name="AppendToFile" value="true" />
<param name="DatePattern" value="yyyy.MM.dd" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="500KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<conversionPattern value="%d %p %m%n" />
</layout>
</appender>
<logger name="NHibernate.SQL">
<level value="ALL" />
<appender-ref ref="rollingFile" />
</logger>
</log4net>

</configuration>
ج) سپس باید فراخوانی زیر نیز در ابتدای کار برنامه صورت گیرد:

log4net.Config.XmlConfigurator.Configure();
در یک برنامه ASP.Net این فراخوانی باید در Application_Start فایل Global.asax.cs صورت گیرد.
یا در یک برنامه از نوع WinForms تنها کافی است سطر زیر را به فایل AssemblyInfo.cs برنامه اضافه کرد:

// Configure log4net using the .config file
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
یا این سطر را به فایل Global.asax.cs یک برنامه ASP.Net نیز می‌توان اضافه کرد. Watch=true آن، با کمک FileSystemWatcher تغییرات فایل کانفیگ را تحت نظر داشته و هر بار که تغییر کند بلافاصله، تغییرات جدید را اعمال خواهد کرد.

د) هنگام استفاده از کتابخانه Fluent NHibernate حتما باید متد ShowSql در جایی که دیتابیس برنامه را تنظیم می‌کنیم (Fluently.Configure().Database) ذکر گردد (که نمونه آن‌را در مثال‌های قسمت‌های قبل ملاحظه‌ کرده‌اید).

توضیحاتی در مورد تنظیمات فوق:
configSections حتما باید در ابتدای فایل app.config‌ ذکر شود و گرنه برنامه کار نخواهد کرد.
سپس کانکشن استرینگ مورد استفاده در قسمت کانفیگ برنامه ذکر شده است.
در ادامه تنظیمات استاندارد مربوط به log4net را مشاهده می‌کنید.
در تنظیمات این کتابخانه، appender مشخص کننده محل ثبت وقایع است. زمانیکه که از RollingFileAppender استفاده کنیم، اطلاعات را در یک سری فایل ذخیره خواهد کرد (امکان ثبت وقایع در EventLog ویندوز، ارسال از طریق ایمیل و غیره نیز میسر است که جهت توضیحات بیشتر می‌توان به مستندات آن رجوع نمود).
سپس نام فایلی که اطلاعات وقایع در آن ثبت خواهند شد ذکر شده است (برای مثال NHibernate_Log.txt)، در ادامه مشخص گردیده که اطلاعات باید هر بار به این فایل Append و اضافه شوند. سطرهای بعدی مشخص می‌کنند که هر زمانیکه این لاگ فایل به 10 مگابایت رسید، یک فایل جدید تولید کن و هر بار 10 فایل آخر را نگه دار و مابقی فایل‌های قدیمی را حذف کن.
در قسمت PatternLayout مشخصات می‌کنیم که خروجی ثبت شده با چه فرمتی باشد. برای مثال یک سطر خروجی مطابق با تنظیمات فوق به شکل زیر خواهد بود:

2009-10-18 20:03:54,187 DEBUG INSERT INTO [Student] (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = 'Vahid'
در قسمت Logger یک نام دلخواه ذکر شده و میزان اطلاعاتی که باید درج شود، از طریق مقدار level مورد نظر، قابل تنظیم است که می‌تواند یکی از مقادیر ALL ،DEBUG ،INFO ،WARN ،ERROR ،FATAL و یا OFF باشد. اینجا level در نظر گرفته شده ALL است که تمامی اطلاعات مرتبط با اعمال پشت صحنه NHibernate را لاگ خواهد کرد.
توسط appender-ref آن appender ایی را که در ابتدای کار تعریف و تنظیم کردیم، مشخص خواهیم کرد.

اگر هم با برنامه نویسی بخواهیم اطلاعاتی را به این لاگ فایل اضافه کنیم تنها کافی است بنویسیم:

log4net.LogManager.GetLogger("NHibernate.SQL").Info("test1");

اطلاعات بیشتر

ادامه دارد ...

مطالب
C# 7 - Throw Expressions
در طراحی زبان #C، واژه‌ی کلیدی throw همیشه یک statement بوده‌است و نه یک expression. برای مثال از آن نمی‌توان در قطعه کدهای شرطی و عبارات lambda استفاده کرد. برای رفع این محدودیت، در C# 7 کار معرفی «throw expressions» صورت گرفته‌است.


throw expressions در C# 7

روش تعریف throw expressions همانند روش متداول تعریف آن‌ها است و از این لحاظ تغییری صورت نگرفته‌است. تنها تغییر انجام شده، امکان استفاده‌ی از آن در محل‌هایی است که پیشتر مجاز نبوده‌است.
برای نمونه قطعه کد متداول ذیل را درنظر بگیرید:
public class MyApiType
{
    private object _loadedResource;
    private object _someProperty;
 
    public MyApiType()
    {
        _loadedResource = LoadResource();
        if (_loadedResource == null) throw new InvalidOperationException();
    }
 
    public object SomeProperty
    {
        get
        {
            return _someProperty;
        }
 
        set
        {
            if (value == null) throw new ArgumentNullException();
            _someProperty = value;
        }
    }
}
در اینجا با روش fail fast، کار بررسی null بودن مقادیر دریافتی در سازنده و همچنین یک خاصیت، صورت گرفته‌اند و در صورت نال بودن، یک استثناء صادر می‌شود.
اکنون در C# 7 می‌توان قطعه کد فوق را به صورت ذیل خلاصه کرد:
public class MyApiType
{
    private object _loadedResource = LoadResource() ?? throw new InvalidOperationException();
    private object _someProperty;
 
    public object SomeProperty
    {
        get
        {
            return _someProperty;
        } 
        set
        {
            _someProperty = value ?? throw new ArgumentNullException();
        }
    }
}
از این جهت که واژه‌ی کلیدی throw در C#7 هم statement است و هم expression، اکنون می‌توان از آن در عبارات شرطی و همچنین null-coalescing expressions نیز استفاده کرد. به علاوه امکان استفاده‌ی از آن‌را در یک «initialization expression» مانند loadedResource_ نیز مشاهده می‌کنید.

به علاوه اگر نکات «Expression-bodied Members» را نیز اعمال کنیم، اینبار به قطعه کد خلاصه‌تر ذیل خواهیم رسید:
public class MyApiType
{
    private object _loadedResource = LoadResource() ?? throw new InvalidOperationException();
    private object _someProperty;
 
    public object SomeProperty
    {
        get => _someProperty;
        set => _someProperty = value ?? throw new ArgumentNullException();
    }
}


یک مثال ترکیبی دیگر

قطعا تا پیش از C# 7 یک چنین بررسی‌های شرطی را در حین تزریق وابستگی‌ها، در سازنده‌ی کلاس‌های سرویس خود انجام داده‌اید:
public partial class ShippingAddressPage
{
    private readonly IWebDriver driver;
    public ShippingAddressPage(IWebDriver driver)
    {
        if (driver == null)
        {
            throw new ArgumentNullException(nameof(driver));
        }
        this.driver = driver;
    }
}
اکنون در C# 7 می‌توان قطعه کد فوق را به صورت ذیل خلاصه کرد:
public partial class ShippingAddressPage
{
    private readonly IWebDriver driver;
    public ShippingAddressPage(IWebDriver driver) =>
      this.driver = driver ?? throw new ArgumentNullException(nameof(driver));
}
که ترکیبی است از throw expressions و همچنین Expression-bodied Members.


مثالی از کاربرد throw expressions در یک conditional ternary operator

private static int ThrowUsageInAnExpression(int value = 40)
{
    return value < 20 ? value : throw new ArgumentOutOfRangeException("Argument value must be less than 20");
}
مثال‌هایی را که تا اینجا بررسی کردیم بیشتر به null-coalescing expressions مرتبط بودند. در اینجا یک نمونه کاربرد throw expression را در یک conditional ternary operator مشاهده می‌کنید.
اشتراک‌ها
رهانش ASP.NET Core updates in .NET 8 Preview 4

.NET 8 Preview 4 is now available and includes many great new improvements to ASP.NET Core.


Here’s a summary of what’s new in this preview release:


Blazor

Streaming rendering with Blazor components

Handling form posts with Blazor SSR

Route to named elements in Blazor

Webcil packaging for Blazor WebAssembly apps

API authoring

Expanded support for form binding in minimal APIs

API project template includes .http file

Native AOT

Logging and exception handling in compile-time generated minimal APIs

ASP.NET Core top-level APIs annotated for trim warnings

Reduced app size with configurable HTTPS support

Worker Service template updates

Additional default services configured in the slim builder

API template JSON configuration changes

Support for JSON serialization of compiler-generated IAsyncEnumerable unspeakable types

Authentication and authorization

Identity API endpoints

Improved support for custom authorization policies with IAuthorizationRequirementData

ASP.NET Core metrics

For more details on the ASP.NET Core work planned for .NET 8 see the full ASP.NET Core roadmap for .NET 8 on GitHub. 

رهانش ASP.NET Core updates in .NET 8 Preview 4
اشتراک‌ها
آموزش رایگان برنامه نویسی Full-Stack به زبان فارسی

C#.NET for non-engineers.

The first course of "A Sr. Developer Course" courses. which contains:
1- C# Fundamentals for non-engineers.
2- DataBase for non-engineers.
3- Asp.NET WebForm for Non-engineers.
4- Application Architecture for no-engineers.
5- ASP.NET MVC for non-engineers.
6- Angular for non-engineers.

This is a course for who knows noting about C# and development if you know nothing about Array, variable, loop, and conditions you are in the right place.
at the end of this course, we will create one small university registration console application together.

You will learn in this course:
C#.NET
.NET Framework
Methods
Recursive methods
C# Primitive Types/Complex Types
conditions
switch case
Arrays
if statement
switch
loops
Creating a method
ref, out
enums
OOP/Object-oriented programing
Generics
Error handling
problem-solving
working with files


level: beginners to upper intermediate 

آموزش رایگان برنامه نویسی Full-Stack به زبان فارسی