مطالب
نحوه ایجاد شمارنده Row_Number() Sql Server در LINQ
چند روز پیش برای انجام یک بخشی از کار پروژه خودم باید از توابع و window function‌ها در sql server  استفاده میکردم که در سایت جاری آشنایی با Row_Number،Rank،Dense_Rank،NTILE و  آشنایی با Window Function‌ها در SQL Server بصورت مفصل توضیح داده شده است.
حال اگر بخواهیم یکی از پرکاربردترین این توابع که Row_Number می‌باشد را در LINQ استفاده کنیم باید به چه صورت عمل کنیم.
من برای پیاده سازی از برنامه نیمه رایگان LINQPad استفاده کردم که میتوانید از سایت اصلی این نرم افزار دانلود نمائید.
پس از دانلود و اجرای آن ، در قسمت بالایی زبان linqpad  را به C# Statement(s) تغییر دهید.
 

سپس کد زیر را به بخش query  انتقال دهید.
string[] mystring = new string[]{"a","b","c","d"};

int i=0;

var s1 = from s in mystring.ToList()
let e = i++
select new {
Row_Number = i,StringName = s
};

s1.Dump();
mystring.Count().Dump("mystring Count");

سپس با زدن کلید F5 یا دکمه اجرای query  نتیجه را مشاهده نمائید.

use-row_number-in-Linq.linq


 
 
مطالب
مرتب سازی صحیح حروف فارسی در بانک اطلاعاتی SQLite
فرض کنید لیست حروف الفبای فارسی را در یک بانک اطلاعاتی SQLite ذخیره کرده‌اید:
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();

var createCommand = connection.CreateCommand();
createCommand.CommandText =
            @"
                CREATE TABLE persian_letter (
                    value TEXT
                );

                INSERT INTO persian_letter
                VALUES ('ا'),('ب'),('پ'),('ت'),('ث'),('ج'),('چ'),('ح'),('خ'),('د'),('ذ'),('ر'),('ز'),('ژ'),('س'),('ش'),
                       ('ص'),('ض'),('ط'),('ظ'),('ع'),('غ'),('ف'),('ق'),('ک'),('گ'),('ل'),('م'),('ن'),('و'),('ه'),('ی');
            ";
createCommand.ExecuteNonQuery();
اگر از این لیست کوئری گرفته و آن‌ها‌را مرتب کنیم:
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
            @"
                SELECT value
                FROM persian_letter
                order by value
            ";
var reader = queryCommand.ExecuteReader();
var sortedDbItems = new List<string>();
while (reader.Read())
{
    sortedDbItems.Add($"{reader["value"]}");
}
یک چنین خروجی حاصل می‌شود:


همانطور که ملاحظه می‌کنید، مرتب سازی حروف فارسی در اینجا به صورت پیش‌فرض کار نمی‌کند. علت اینجا است که روش پیش‌فرض مرتب سازی حروف در SQLite، بر اساس کد اسکی حروف است و فقط در مورد حروف ASCII از A تا Z درست کار می‌کند.


امکان تعریف Collation سفارشی در SQLite

در بانک‌های اطلاعاتی، قابلیتی که مستقیما بر روی نحوه‌ی جستجو و همچنین مرتب سازی حروف تاثیر می‌گذارد، Collation نام دارد و در SQLite برخلاف بسیاری از بانک‌های اطلاعاتی دیگر، امکان تعریف Collation سفارشی نیز وجود دارد و برای این منظور باید یک function pointer را در اختیار آن قرار داد تا از آن در سمت بانک اطلاعاتی جهت مرتب سازی و جستجوی حروف استفاده کند.
خوشبختانه پروژه‌ی Microsoft.Data.Sqlite امکان تبدیل یک managed delegate دات نتی را به یک function pointer مخصوص SQLite، میسر می‌کند. به عبارتی SQLite کدهای دات نتی را در حین انجام محاسبات خود اجرا خواهد کرد و این اجرا به صورتی نیست که ابتدا کل اطلاعات، به سمت برنامه‌ی کلاینت منتقل شود و سپس در این سمت، در حافظه، عملیاتی بر روی آن صورت گیرد. کل عملیات در سمت بانک اطلاعاتی مدیریت می‌شود.
روش تعریف یک Collation جدید هم در اینجا بسیار ساده‌است:
connection.CreateCollation("PersianCollationNoCase", (x, y) => string.Compare(x, y, ignoreCase: true));
فقط کافی است بر روی اتصال باز شده، متد CreateCollation فراخوانی و نحوه‌ی مقایسه‌ی دو رشته مشخص شود. سپس این Collation نامدار، به صورت زیر در کوئری‌ها قابل استفاده خواهد بود:
SELECT value
FROM persian_letter
order by value COLLATE PersianCollationNoCase
اینبار اگر خروجی برنامه را بررسی کنیم، مشاهده خواهیم کرد که مرتب سازی حروف فارسی در SQLite به درستی کار می‌کند:



تعریف Collation سفارشی غیرحساس به «ی و ک» !

این مورد شاید یکی از آرزوهای توسعه دهندگان SQL Server باشد! اما با SQLite به سادگی زیر قابل تعریف و مدیریت است:
connection.CreateCollation("PersianCollationNoCaseYekeInsensitive",
(x, y) => string.Compare(x.ApplyCorrectYeKe(), y.ApplyCorrectYeKe(), ignoreCase: true));
متد ApplyCorrectYeKe فوق از بسته‌ی نیوگت DNTPersianUtils.Core دریافت شده و کار آن یک‌دست کردن «ی و ک» فارسی و عربی است.
در یک چنین حالتی اگر اطلاعاتی را به همراه «ی و ک» فارسی و یا عربی ثبت کنیم:
CREATE TABLE persian_letter (
value TEXT
);
INSERT INTO persian_letter
VALUES ('ی'),('ک');
جستجوی بر روی آن‌ها دیگر وابسته‌ی به مقدار «ی و ک» وارد شده نبوده و چه «ی و ک» فارسی وارد شود و چه عربی، این کوئری همواره کار می‌کند:
SELECT count()
FROM persian_letter
WHERE value = 'ی' COLLATE PersianCollationNoCaseYekeInsensitive


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید: SQLitePersianCollation.zip
بازخوردهای پروژه‌ها
عدم نمایش متن در هدر سفارشی
با عرض سلام و خسته نباشید؛ میخوام توی گزارش از هدر سفارشی استفاده کنم و به صورت HTML یه چیزی درست کردم (تستی) اما متن پیغام نشون داده نمیشه.
کدی که استفاده کردم:
                    header.XHtmlHeader(rptHeader =>
                    {
                        rptHeader.PageHeaderProperties(new XHeaderBasicProperties
                        {
                            RunDirection = PdfRunDirection.RightToLeft,
                            ShowBorder = true,
                            //ImagesPath = Path.Combine(AppPath.ApplicationPath, "images\\report-logo.png")
                        });
                        rptHeader.AddPageHeader(pageHeader =>
                        {
                            string message = "گزارش تراکنش‌های مالی ریز پرداخت ها";
                            var photo = Path.Combine(AppPath.ApplicationPath, "images\\report-logo.png");
                            var image = string.Format("<img src='{0}' width='150' />", photo);

                            return string.Format(@"<table style='width:100%;direction:rtl;font-size:15px;'>
            <tr>
            <td style='width:20%;'>{2}</td>
            <td style='width:60%;'>{1}</td>
            <td style='width:20%;'>{0}</td>
            </tr>
                </table>", image, message, DateTime.Now.ToString("yyyy/MM/dd"));
                        });
                    });

و نتیجه ای که می‌گیرم:


ممنون میشم راهنمایی بفرمایید.
مطالب
C# 8.0 - Using declarations
یکی دیگر از ویژگی‌های جدید C# 8.0، پشتیبانی از using declarations (اعلان‌های using) در مقابل using statements (عبارات using) پیشین است که سبب می‌شود بتوان کدهای کمتری را برای تعریف آن‌ها نوشت.


مثالی از using declarations

تا پیش از C# 8.0، روش متداول کار با عبارات using به صورت زیر است و به آن استفاده از using statements گفته می‌شود:
    class Program
    {
        static void UsingOld()
        {
            using (var file = new FileStream("input.txt", FileMode.Open))
            using (var reader = new StreamReader(file))
            {
                var s = reader.ReadToEnd();

                // Do something with data
            }
        }
که در نهایت پس از پایان این قطعه کد، هر دو شیء file و reader به صورت خودکار Dispose می‌شوند.
اکنون در C# 8.0 می‌توان قطعه کد فوق را به کمک using declarations به صورت زیر خلاصه کرد:
    class Program
    {
        static void UsingNew(string[] args)
        {
            using Stream file = new FileStream("input.txt", FileMode.Open);
            using StreamReader reader = new StreamReader(file);

            var s = reader.ReadToEnd();

            // Do something with data
        }
که در اینجا پرانتزها و همچنین {} ها، حذف شده‌اند.


میدان دید using declarations

پس از این تغییرات، سؤال مهمی که مطرح می‌شود این است: متغیرهایی که توسط using declaration تعریف می‌شوند، تا چه زمانی زنده نگه داشته می‌شوند. به عبارتی متد UsingOldScope آیا همانند متد UsingNewScope عمل می‌کند؟ آیا متغیر buffer آن همانند متد UsingOldScope خارج از میدان دید usingها قرار می‌گیرد؟
    class Program
    {
        static void UsingNewScope()
        {
            string buffer = null;
            using Stream file = new FileStream("input.txt", FileMode.Open);
            using StreamReader reader = new StreamReader(file);

            buffer = reader.ReadToEnd();

            // Do something with data

            buffer = null;
        }

        static void UsingOldScope(string[] args)
        {
            string buffer = null;

            using (var file = new FileStream("input.txt", FileMode.Open))
            using (var reader = new StreamReader(file))
            {
                buffer = reader.ReadToEnd();
            }

            // Do something with data

            buffer = null;
        }
زمانیکه از using statements استفاده می‌شود (مانند متد UsingOldScope)، توسط آن یک scope نیز تعریف می‌شود (داخل {} ها) که در پایان آن، کار فراخوانی متد Dispose اشیاء IDisposable ارجاعی، به صورت خودکار انجام می‌شود. این فراخوانی نیز توسط کامپایلر در داخل یک قطعه کد try/finally صورت می‌گیرد تا حتی اگر در این بین استثنائی نیز رخ داد، حتما متد Dispose فراخوانی گردد.
اما زمانیکه از using declarations استفاده می‌شود (مانند متد UsingNewScope)، دیگر این {} را نداریم. اینبار scope تعریف شده، تا «پایان متد» ادامه پیدا می‌کند و سپس متد Dispose اشیاء ارجاعی، فراخوانی می‌گردد. بدیهی است در اینجا نیز همانند قبل، همان قطعه کد try/finally توسط کامپایلر جهت فراخوانی متد Dispose، تشکیل خواهد شد. بنابراین اگر بخواهیم متد UsingNewScope را توسط using statements پیشین بازنویسی کنیم، به یک چنین قطعه کدی خواهیم رسید که scope پس از using declarations، تا آخر متد ادامه پیدا می‌کند:
    string buffer = null; 
    using (var file = new FileStream("input.txt", FileMode.Open)) 
    { 
        using (var reader = new StreamReader(file)) 
        { 
            buffer = reader.ReadToEnd(); 
            buffer = null; 
        } 
    }


سؤال: آیا امکان محدود کردن میدان دید using declarations وجود دارد؟

پاسخ: بله. می‌توان با تعریف یک {}، میدان دید متغیرهای ارجاعی توسط using declarations را محدود کرد:
private static void UsingDeclarationWithScope()
{
    {
        using var r1 = new AResource();
        r1.UseIt();
    }  // r1 is disposed here!
    Console.WriteLine("r1 is already disposed");
}
در اینجا جائیکه {} بسته می‌شود، متغیر r1 از میدان دید خارج شده و بلافاصله Dispose خواهد شد.


سؤال: آیا using declarations تمام قابلیت‌های using statements را ارائه می‌دهند؟

پاسخ: خیر. فرض کنید کلاس AResource از نوع IDisposable تعریف شده‌است:
    public class AResource : IDisposable
    {
        public void UseIt() => Console.WriteLine(nameof(UseIt));
        public void Dispose() => Console.WriteLine($"Dispose {nameof(AResource)}");
    }
و سپس متدی، وهله‌ای از این کلاس را باز می‌گرداند:
    class Program
    {
        public static AResource GetTheResource() => new AResource();
با استفاده از using statements، نوشتن چنین قطعه کدی بدون تعریف متغیری مجاز است:
using (GetTheResource())
{
   // do something here
}  // resource is disposed here
اما اگر اینکار را توسط using declarations انجام دهیم، به چندین خطای کامپایلر خواهیم رسید:
using GetTheResource(); // Compiler error
علت اینجا است که برخلاف using statements، ذکر متغیرهای scope برای using declarations اجباری است. برای رفع آن می‌توان از یک discard استفاده کرد:
using var _ = GetTheResource(); // Works fine
مطالب
آموزش زبان Rust - قسمت 8 - Rust-Based CS Masterclass
مدیریت حافظه، نقش مهمی را در برنامه نویسی ایفا می‌کند و بر عملکرد و کارآیی یک برنامه تاثیر می‌گذارد. این مقاله، مروری را بر سه نوع حافظه‌ی اصلی ارائه می‌کند:  static memory, stack memory, heap . درک تفاوت بین این انواع حافظه‌ها می‌تواند به شما در بهینه سازی کد و جلوگیری از مشکلات احتمالی، کمک کند.


Static Memory

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

مواردی که در حافظه استاتیک قرار میگیرند :
  • Program Binary
  • Static variables
  • String Literals (in Rust)

Size :
  Fixed ( محاسبه در زمان کامپایل )
Lifetime : برابر با طول عمر برنامه
پاکسازی : به صورت خودکار ؛ زمانی که برنامه متوقف میشود .


  Stack Memory

حافظه‌ی پشته، مسئول نگهداری آرگومان‌های تابع و متغیرهای محلی است. پشته، شامل stack frames است که برای هر فراخوانی تابع در زنجیره‌ای از فراخوانی‌های تابع، ایجاد می‌شوند (به عنوان مثال، A B را فرا می‌خواند، B C را فرا می‌خواند). حافظه‌ی پشته به اندازه‌ی مشخصی در زمان کامپایل نیاز دارد؛ به این معنا که آرگومان‌ها و متغیرهای درون  stack frames باید اندازه‌های از پیش تعیین شده‌ای داشته باشند. اندازه‌ی پشته، پویا است؛ اما دارای حد بالایی ثابتی است که در هنگام راه اندازی برنامه تعریف شده‌است. حافظه‌ی پشته، دارای طول عمری برابر با طول عمر عملکرد است و هنگامیکه عملکرد، نتیجه‌ای را بر می‌گرداند، پاکسازی آن خودکار است.  

بیایید نگاهی به یک مثال ساده در Rust بیندازیم تا حافظه‌ی پشته را بهتر درک کنیم:
fn add(x: i32, y: i32) -> i32 {
    let sum = x + y;
    sum
}

fn main() {
    let a = 5;
    let b = 3;
    let result = add(a, b);
    println!("The sum is: {}", result);
}
در این برنامه‌ی Rust، دو عملکرد add و main را داریم. هنگامیکه برنامه شروع به اجرا می‌کند، یک stack frames برای تابع اصلی در حافظه‌ی پشته ایجاد می‌شود. این  stack frames شامل متغیرهای محلی a، b و فراخوانی تابع برای add(a, b) است.
هنگامیکه تابع add فراخوانی می‌شود، یک stack frames دیگر در بالای stack frames main موجود ایجاد می‌شود. این stack frames جدید حاوی متغیرهای محلی x، y و sum است. مقادیر a و b به عنوان آرگومان به تابع add ارسال می‌شوند و به ترتیب در x و y ذخیره می‌شوند. پس از محاسبه‌ی مجموع، تابع add، مقداری را بر می‌گرداند و  stack frames آن به طور خودکار از حافظه‌ی پشته حذف می‌شود.
سپس تابع main، مقدار برگشتی را از تابع add دریافت می‌کند و به نتیجه‌ی متغیر اختصاص می‌یابد. از ماکروی println! برای چاپ نتیجه استفاده می‌شود. پس از اتمام اجرای برنامه و بازگشت تابع اصلی، stack frames آن نیز از حافظه‌ی پشته حذف می‌شود و حافظه به‌طور خودکار پاک می‌شود.
در این مثال، می‌توانید ببینید که چگونه از stack frames برای ذخیره‌ی آرگومان‌های تابع و متغیرهای محلی در Rust استفاده می‌شود. اندازه‌ی این متغیرها در زمان کامپایل مشخص می‌شود و طول عمر حافظه‌ی پشته، برابر با طول عمر تابع است. هنگامیکه تابع برمی‌گردد، فرآیند پاکسازی آن خودکار است و قاب پشته‌ی مربوطه را حذف می‌کند.


Heap Memory

حافظه‌ی Heap، مقادیری را ذخیره می‌کند که باید فراتر از طول عمر یک تابع مانند مقادیر بزرگ و مقادیر قابل دسترسی توسط رشته‌های متعدد، زنده بمانند. از آنجائیکه هر رشته دارای پشته‌ی مخصوص به خود است، همه‌ی آنها یک پشته‌ی مشترک دارند. حافظه‌ی Heap می‌تواند مقادیری با اندازه‌ی ناشناخته را در زمان کامپایل، در خود جای دهد؛ مانند رشته‌های ورودی کاربر. اندازه‌ی پشته نیز پویا است؛ با حد بالایی ثابت که در زمان راه اندازی برنامه تعیین می‌شود. حافظه‌ی Heap طول عمری دارد که توسط برنامه نویس تعیین می‌شود و برنامه نویس تصمیم می‌گیرد که چه زمانی باید حافظه تخصیص داده شود. پاکسازی حافظه‌ی هیپ به صورت دستی است و نیاز به مداخله‌ی برنامه نویس دارد.
در این مثال ساده، روش استفاده از حافظه‌ی پشته نشان داده می‌شود:
use std::rc::Rc;

#[derive(Debug)]
struct LargeData {
    data: Vec<i32>,
}

impl LargeData {
    fn new(size: usize) -> LargeData {
        LargeData {
            data: vec![0; size],
        }
    }
}

fn main() {
    let large_data = Rc::new(LargeData::new(1_000_000));
    let shared_data1 = Rc::clone(&large_data);
    let shared_data2 = Rc::clone(&large_data);

    println!("{:?}", shared_data1);
    println!("{:?}", shared_data2);
}
در این برنامه‌ی Rust، یک ساختار LargeData را تعریف می‌کنیم که حاوی <Vec<i32 است. این روش جدید، یک شیء LargeData را به اندازه‌ی مشخصی مقداردهی اولیه می‌کند. در تابع main، یک شیء LargeData را با اندازه (1,000,000 عنصر) ایجاد می‌کنیم و با استفاده از Rc::new روی پشته ذخیره می‌کنیم. Rc یک اشاره‌گر شمارش مرجع است که به چندین متغیر اجازه می‌دهد تا مالکیت داده‌های تخصیص داده شده را به اشتراک بگذارند (در ادامه‌ی دوره توضیح داده خواهد شد).  
سپس دو متغیر دیگر را به نام‌های shared_data1 و shared_data2 ایجاد می‌کنیم که با استفاده از Rc::clone، یک شیء LargeData تخصیص‌یافته‌ی مشابه را به اشتراک می‌گذارند. این نشان می‌دهد که چگونه حافظه‌ی پشته را می‌توان در بین متغیرهای متعددی به اشتراک گذاشت؛ حتی فراتر از طول عمر تابع اصلی که داده را ایجاد کرده است.
در این مثال، پاکسازی حافظه‌ی پشته به طور خودکار توسط مکانیزم شمارش مرجع Rust مدیریت می‌شود (در ادامه‌ی دوره توضیح داده خواهد شد). هنگامیکه تعداد مرجع نشانگر Rc به صفر می‌رسد (یعنی وقتی همه‌ی متغیرهایی که داده‌ها را به اشتراک می‌گذارند از محدوده خارج می‌شوند)، حافظه‌ی تخصیص داده شده، روی پشته تخصیص داده می‌شود.
این مثال نشان می‌دهد که چگونه می‌توان از حافظه‌ی پشته برای ذخیره‌ی ساختارهای داده یا مقادیر بزرگی استفاده کرد که باید بیشتر از طول عمر یک تابع باشند و چگونه می‌توان حافظه‌ی پشته را بین چندین متغیر به اشتراک گذاشت.
مطالب
پیاده سازی UnitOfWork برای BrightStarDb
 در این پست با BrightStarDb و مفاهیم اولیه آن آشنا شدید. همان طور که پیش‌تر ذکر شد BrightStarDb از تراکنش‌ها جهت ذخیره اطلاعات پشتیبانی می‌کند. قصد داریم روش شرح داده شده در اینجا را بر روی BrightStarDb فعال کنیم. ابتدا بهتر است با روش ساخت مدل در B*Db آشنا شویم.
*یکی از پیش نیاز‌های این پست مطالعه این دو مطلب (^ )  و (^ ) می‌باشد.
فرض می‌کنیم در دیتابیس مورد نظر یک Store به همراه یک جدول به صورت زیر داریم:
[Entity]
    public interface IBook
    {
        [Identifier]
        string Id { get; }

        string Title { get; set; }

        string Isbn { get; set; }
    }
بر روی پروژه مورد نظر کلیک راست کرده و گزینه Add new Item را انتخاب نمایید. از برگه Data  گزینه BrightStar Entity Context را انتخاب کنید

بعد از انخاب گزینه بالا یک فایل با پسوند tt به پروژه اضافه خواهد شد که وظیفه آن جستجو در اسمبلی مورد نظر و پیدا کردن تمام اینترفیس هایی که دارای  EntityAttribute هستند و همچنین ایجاد کلاس‌های متناظر جهت پیاده سازی اینترفیس‌های بالا است. در نتیجه ساختار پروژه تا این جا به صورت زیر خواهد شد.

واضح است که فایلی به نام Book به عنوان پیاده سازی مدل IBook  به عنوان زیر مجموعه فایل DatabaseContext.tt به پروژه اضافه شده است.

تا اینجا برای استفاده از Context مورد نظر باید به صورت زیر عمل نمود:

DatabaseContext context = new DatabaseContext();    
  context.Books.Add(new Book());
Context پیش فرض ساخته شده توسط B*Db از Generic DbSet‌های معادل EF پشتیبانی نمی‌کند و از طرفی IUnitOfWork مورد نظر به صورت زیر است
public interface IUnitOfWork
    {
        BrightstarEntitySet<T> Set<T>() where TEntity : class;
        void DeleteObject(object obj); 
         void SaveChanges();
    }
در اینجا فقط به جای  IDbSet از BrightStarDbSet استفاده شده است. همان طور که در این مقاله توضیح داده شده است، برای پیاده سازی مفهوم UnitOfWork؛ نیاز است تا کلاس DatabaseContext که نماینده BrightStarDbContext پروژه است، از اینترفیس IUnitOfWork طراحی شده ارث بری کند. جهت انجام این مهم  و همچنین جهت اضافه کردن قابلیت ایجاد Generic DbSet‌ها نیز باید کمی در فایل Template Generator تغییر ایجاد نماییم. این تغییرات را قبلا در طی یک پروژه ایجاد کرده‌ام و شما می‌توانید آن را از اینجا دریافت کنید. بعد از دانلود کافیست فایل DatabaseContext.tt مورد نظر را در پروژه خود کپی کرده و گزینه Run Custom Tools را فراخوانی نمایید.

نکته: برای حذف یک آبجکت از Store، باید از متد DeleteObject تعبیه شده در Context استفاده نماییم. در نتیجه متد مورد نظر نیز در اینترفیس بالا در نظر گرفته شده است.

استفاده از IOC Container جهت رجیستر کردن IUnitOfWrok
در این قدم باید IUnitOfWork را در یک IOC container رجیستر کرده تا در جای مناسب عملیات وهله سازی از آن میسر باشد. من در اینجا از Castle Windsor Container استفاده کردم. کلاس زیر این کار را برای ما انجام خواهد داد:
 public class DependencyResolver
    {
        public static void Resolve(IWindsorContainer container)
        {
            var context = new DatabaseContext("type=embedded;storesdirectory=c:\brightstar;storename=test ");
            container.Register(Component.For<IUnitOfWork>().Instance(context).LifestyleTransient());
        }
    }
حال کافیست در کلاس‌های سرویس برنامه UnitOfWork رجیستر شده را به سازنده آن‌ها تزریق نماییم.
public class BookService
    {
        public BookService(IUnitOfWork unitOfWork)
        {
            UnitOfWork = unitOfWork;
        }

        public IUnitOfWork UnitOfWork
        {
            get;
            private set;
        }

        public IList<IBook> GetAll()
        {
            return UnitOfWork.Set<IBook>().ToList();
        }

        public void Add()
        {
            UnitOfWork.Set<IBook>().Add(new Book());
        }

        public void Remove(IBook entity)
        {
            UnitOfWork.DeleteObject(entity);
        }
    }
سایر موارد دقیقا معادل مدل EF آن است.
نکته: در حال حاضر امکان جداسازی مدل‌های برنامه (تعاریف اینترفیس) در قالب یک پروژه دیگر(نظیر مدل CodeFirst در EF) در B*Db امکان پذیر نیست.
نکته : برای اضافه کردن آیتم جدید به Store نیاز به وهله سازی از اینترفیس IBook داریم. کلاس Book ساخته شده توسط DatabaseContext.tt در عملیات Insert و update کاربرد خواهد داشت.

بازخوردهای دوره
بررسی Semantic Search و FTS Table-valued functions
با سلام
 SEMANTICSIMILARITYTABLE آیا برای متون فارسی هم کار می‌کند.
من تست کردم نتیجه‌ای برای رکورهایی که با متون فارسی پر شدن بر نمی‌گردونه!  
نظرات اشتراک‌ها
بومی سازی پیام‌های خطای Asp.Net Identity 2.2
با سلام
می‌خواستم ببینم برای فارسی کردن پیام‌ها در asp.net identity چیکار باید بکنم؟تو اون لیست فارسی نیست.با تشکر