Entity Framework Code First使用DbContext查詢

libingql發表於2013-10-16

  DbContext、DbSet及DbQuery是Entity Framework Code First引入的3個新的類,其中DbContext用於保持資料庫會話連線,實體變化跟蹤及儲存,DbSet用於暫存實體類的變化跟蹤,DbQuery用於提供查詢跟你。

  1、使用Set查詢全部記錄

  使用DbContext查詢首先需要保證DbContext的例項在使用完之後對資源的釋放,釋放DbContext例項資源的方法有兩種:採用using程式碼塊結構和呼叫DbContext例項的Dispose()方法。

using (var ctx = new PortalContext())
{
    foreach (var province in ctx.Provinces)
    {
        Console.WriteLine(province.ProvinceName);
    }
}
using (var ctx = new PortalContext())
{
    foreach (var province in ctx.Set<Province>())
    {
        Console.WriteLine(province.ProvinceName);
    }
}

  2、使用LINQ排序、篩選等

  1>、LINQ排序

  LINQ表示式排序:

using (var ctx = new PortalContext())
{
    var provinces = from p in ctx.Provinces
                    orderby p.ProvinceNo
                    select p;
    foreach (var province in provinces)
    {
        Console.WriteLine(province.ProvinceName);
    }
}

  LINQ表示式多欄位排序:

using (var ctx = new PortalContext())
{
    var provinces = from p in ctx.Provinces
                    orderby p.ProvinceNo descending, p.ProvinceName ascending
                    select p;
    foreach (var province in provinces)
    {
        Console.WriteLine(province.ProvinceName);
    }
}

  LINQ擴充套件方法排序:

using (var ctx = new PortalContext())
{
    var provinces = ctx.Provinces
        .OrderBy(p => p.ProvinceNo);

    foreach (var province in provinces)
    {
        Console.WriteLine(province.ProvinceName);
    }
}

  LINQ擴充套件方法多欄位排序:

var provinces = ctx.Provinces
    .OrderByDescending(p => p.ProvinceNo)
    .ThenBy(p => p.ProvinceName);

foreach (var province in provinces)
{
    Console.WriteLine(province.ProvinceName);
}

  注:在採用LINQ擴充套件方法進行多欄位排序時,多出現多個OrderBy,則只按最後一個OrderBy欄位進行排序。

  如下示例只會按照ProvinceName進行升序排序:

var provinces = ctx.Provinces
    .OrderByDescending(p => p.ProvinceNo)
    .OrderBy(p => p.ProvinceName);

  2>、LINQ篩選

  LINQ表示式篩選:

using (var ctx = new PortalContext())
{
    var cities = from c in ctx.Cities
                 where c.ProvinceID == 3
                 select c;

    foreach (var city in cities)
    {
        Console.WriteLine(city.CityName);
    }
}

  LINQ表示式多欄位篩選:

using (var ctx = new PortalContext())
{
    var cities = from c in ctx.Cities
                 where c.ProvinceID == 3 && c.CityID > 10
                 select c;

    foreach (var city in cities)
    {
        Console.WriteLine(city.CityName);
    }
}

  LINQ表示式篩選與排序:

using (var ctx = new PortalContext())
{
    var cities = from c in ctx.Cities
                 where c.ProvinceID == 3 && c.CityID > 10
                 orderby c.CityID
                 select c;

    foreach (var city in cities)
    {
        Console.WriteLine(city.CityName);
    }
}

  LINQ擴充套件方法篩選:

using (var ctx = new PortalContext())
{
    var cities = ctx.Cities
        .Where(c => c.ProvinceID == 3);

    foreach (var city in cities)
    {
        Console.WriteLine(city.CityName);
    }
}

  LINQ擴充套件方法多欄位篩選:

using (var ctx = new PortalContext())
{
    var cities = ctx.Cities
        .Where(c => c.ProvinceID == 3 && c.ProvinceID > 10);

    foreach (var city in cities)
    {
        Console.WriteLine(city.CityName);
    }
}

  LINQ擴充套件方法多欄位篩選及排序:

var cities = ctx.Cities
    .Where(c => c.ProvinceID == 3 && c.ProvinceID > 10)
    .OrderBy(c=>c.CityID);

  3>、LINQ選擇讀取欄位

  LINQ表示式讀取1個欄位:

var cities = from c in ctx.Cities
             where c.ProvinceID == 3 && c.CityID > 10
             select c.CityName;

  LINQ表示式讀取多個欄位:

var cities = from c in ctx.Cities
             where c.ProvinceID == 3 && c.CityID > 10
             select new { c.CityID, c.CityName };

  LINQ擴充套件方法讀取1個欄位:

using (var ctx = new PortalContext())
{
    var citieNames = ctx.Cities
        .Where(c => c.ProvinceID == 3 && c.ProvinceID > 10)
        .OrderBy(c => c.CityID)
        .Select(c => c.CityName);

    foreach (var cityName in citieNames)
    {
        Console.WriteLine(cityName);
    }
}

  LINQ擴充套件方法讀取多個欄位:

using (var ctx = new PortalContext())
{
    var cities = ctx.Cities
        .Where(c => c.ProvinceID == 3 && c.ProvinceID > 1)
        .OrderBy(c => c.CityID)
        .Select(c => new { c.CityID, c.CityName });

    foreach (var c in cities)
    {
        Console.WriteLine("{0}-{1}", c.CityID, c.CityName);
    }
}

  3、查詢本地資料

  Entity Framework Code First通過DbSet的Local屬性查詢本地資料,查詢本地資料的使用情況:1>當需要查詢的資料已經存在與記憶體中,而不想再次傳送SQL語句到資料庫中取查詢;2>當最新的資料還只在記憶體中而未提交到資料庫的情況對記憶體資料進行查詢。

  示例:初始時本地未載入記憶體資料

using (var ctx = new PortalContext())
{
    var count = ctx.Cities.Local.Count;
    Console.WriteLine("Cities in memory:{0}", count);
}

  執行後返回的結果:

  Cities in memory:0

  示例:先通過查詢,將資料載入到記憶體

using (var ctx = new PortalContext())
{
    foreach (var city in ctx.Cities)
    {
        Console.WriteLine(city.CityName);
    }

    var count = ctx.Cities.Local.Count;
    Console.WriteLine("Cities in memory:{0}", count);
}

  執行後返回的結果:

  ......

  Cities in memory:342

  3.2>、使用Load方法將資料載入到記憶體

using (var ctx = new PortalContext())
{
    ctx.Cities.Load();
    var count = ctx.Cities.Local.Count;
    Console.WriteLine("Cities in memory:{0}", count);
}

  執行後的結果:

  Cities in memory:342

using (var ctx = new PortalContext())
{
    var expr = from c in ctx.Cities
               select c;
    expr.Load();
    var count = ctx.Cities.Local.Count;
    Console.WriteLine("Cities in memory:{0}", count);
}

  3.2>、基於本地資料進行查詢

using (var ctx = new PortalContext())
{
    ctx.Cities.Load();
    var cities = from c in ctx.Cities.Local
                orderby c.ProvinceID
                select c;
    foreach (var city in cities)
    {
        Console.WriteLine("{0}", city.CityName);
    }
}

  清除記憶體資料:

ctx.Cities.Local.Clear();

  4、查詢單個物件

  DbContext API可以使用DbSet.Find來查詢返回單個物件,DbSet.Find接受的引數值為需要查詢的主鍵值,若未找到符合條件的主鍵值則返回null。

  Find查詢單個物件的規則:

  1>、從記憶體中查詢已經存在的從資料庫中載入出來的實體或已經被附加到DbContext的實體;

  2>、查詢新新增的但還未被提交儲存到資料庫中的實體物件;

  3>、到資料庫中取查詢還未載入到記憶體中的實體物件。

using (var ctx = new PortalContext())
{
    var city = ctx.Cities.Find(1);

    if (city != null)
    {
        Console.WriteLine(city.CityName);
    }
    else
    {
        Console.WriteLine("City not found!");
    }
}

  若實體類具有多個主鍵,則Find方法同樣接受全部主鍵的引數值,引數的順序必須與主鍵列的順序相同。

var city = ctx.Cities.Find(keyID, cityID);

  Single方法也可以用於查詢後返回單個物件:

using (var ctx = new PortalContext())
{
    var expr = from c in ctx.Cities
                where c.CityID == 1
                select c;

    var city = expr.Single();
}

  SingleOrDefault方法查詢返回單個物件:

using (var ctx = new PortalContext())
{
    var expr = from c in ctx.Cities
                where c.CityID == 1
                select c;
    var city = expr.SingleOrDefault();
    if (city != null)
    {
        Console.WriteLine(city.CityName);
    }
    else
    {
        Console.WriteLine("City not found!");
    }
}

  Single與SingleOrDefault方法的區別在於:當不存在滿足條件的單個實體時,Single將直接丟擲異常,而SingleOrDefault則返回class型別的預設值null。

相關文章