MVC3+EF4.1學習系列(九)-----EF4.1其他的一些技巧的使用

來源:互聯網
上載者:User

標籤:tin   gets   關閉   進一步   any   config   預設   jpg   each   

上節通過一系列重構 簡單的項目就實現了 不過還有些EF的功能沒有講 這節就通過項目 講講EF其他的功能與技巧

一.直接執行SQL語句

通常來講 EF 不用寫SQL語句的  但是 在有些場合  比如對產生的SQL語句 覺得不滿意 要做最佳化  或者做報表統計時 要寫很變態的SQL語句

再或者 大量操作等   這個時候 使用ORM的弱點就顯露了出來 但是 做為優秀的ORM架構  EF 是支援原生態的SQL的   這裡面 提供了三種方法

1. DbSet.SqlQuery   有跟蹤狀態的查詢 

2. DbDatabase.SqlQuery   沒有跟蹤狀態的查詢  

3. DbDatabase.SqlCommand 直接執行SQL語句 一般用來  批量 增刪改

下面 讓我們來看下使用方法

再上篇的公用資產庫裡  添加方法

   public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
{
return dbSet.SqlQuery(query, parameters);
}


public virtual IEnumerable<TEntity> GetwhithdbSql(string query, params object[] parameters)
{
return context.Database.SqlQuery<TEntity>(query, parameters);
}

通過對比 來介紹下 第一個和第二個的區別~~

在課程式控制制器下 分別執行這兩個方法

  var query = "SELECT * FROM Course WHERE CourseID = @p0";
Course course = unitofwork.CourseRepository.GetWithRawSql(query,id).Single();
EntityState state = unitofwork.GetState(course);
string name=course.Department.Name;

Course coursetwo = unitofwork.CourseRepository.GetwhithdbSql(query, id).Single();
EntityState statetwo = unitofwork.GetState(coursetwo);
string nametwo = coursetwo.Department.Name;

 執行後的結果

1.先來看第一個  他的狀態是unchanged  也就說 他加入了context上下文中  有跟蹤狀態

並且下面順利讀取出course.Department.Name   也就是可以讀取到導覽屬性

2.再看來看第二個 他的狀態是detached 並沒有加入到 context上下文中  沒有有跟蹤狀態

所以 我們下面的讀取導覽屬性的內容時  會報錯~~

3.再來說說DbDatabase.SqlCommand  這個比較簡單 增刪改用這個不錯  下面說個批次更新的例子~

假設有需求 更新所有的課程學分為N時   在這種大量操作時 用ORM 架構 就會不太方便了 這時我們可以用這個直接執行SQL語句

這個業務屬於課程的  所以繼承通用資產庫類  代碼如下

using System;
using ContosoUniversity.Models;

namespace ContosoUniversity.DAL
{
public class CourseRepository : GenericRepository<Course>
{
public CourseRepository(SchoolContext context)
: base(context)
{
}

public int UpdateCourseCredits(int multiplier)
{
return context.Database.ExecuteSqlCommand("UPDATE Course SET Credits = Credits * {0}", multiplier);
}

}
}

修改上篇的UnitOfWork類 

private CourseRepository courseRepository;

public CourseRepository CourseRepository
{
get
{

if (this.courseRepository == null)
{
this.courseRepository = new CourseRepository(context);
}
return courseRepository;
}
}

控制器如下

public ActionResult UpdateCourseCredits(int? multiplier)
{
if (multiplier != null)
{
ViewBag.RowsAffected = unitOfWork.CourseRepository.UpdateCourseCredits(multiplier.Value);
}
return View();
}

最後添加視圖~~ 

運行結果圖

 

二.無跟蹤查詢

EF再預設的時候給我們開啟了跟蹤查詢  這個跟蹤的是什麼呢? 先來介紹下這個  看下面的代碼

 Department  duplicateDepartment = db.Departments
.Where(d => d.InstructorID == department.InstructorID)
.FirstOrDefault();

duplicateDepartment.Name = "wuhawuha";

bool IsUpdate=db.Entry<Department>(duplicateDepartment).Property(p => p.Name).IsModified; //是否修改
string now= db.Entry<Department>(duplicateDepartment).Property(p => p.Name).CurrentValue; //現在的值
string before = db.Entry<Department>(duplicateDepartment).Property(p => p.Name).OriginalValue; //以前的值

我們先隨便查出一個院系資訊 修改他的名字 這是我們會通過上面的資訊 得到現在的值  以前的值  這就是跟蹤幫我們做的事  下面看下無跟蹤的

實現無跟蹤很簡單  在查詢時 加上asNoTracking() 即可. 加上後我們發現 明明發生變化了 但是IsUpdate依然為false。而且在 擷取以前的值時 拋出了異常。

通常情況 我們並不需要跟蹤這些狀態 可以在查詢時去掉跟蹤查詢,可以使得效能 得到提升~ 以前一直覺得去掉這個會影響導覽屬性的使用 但是測試後  並沒有影響~

這個跟蹤查詢 還會帶來另一個問題    看下面的圖

 

這是在修改前  加了句  先查詢這個修改的 再修改 這是就會報錯  ObjectStateManager 中已存在具有同一鍵的對象。ObjectStateManager 無法跟蹤具有相同鍵的多個對象。

遇到這個錯誤  在查詢時 加上asNoTracking() 即可.  目前在用EF時 個人並不喜歡有跟蹤狀態~~ 喜歡加上asNoTracking() 

三.使用代理

瞭解過ORM架構的  我們知道 導覽屬性 使用了代理模式 ,這個代理 也是跟導覽屬性有關的 。 禁用代理 可以提高序列化的速度 .

關閉代理的代碼為在繼承 dbcontext 的類裡  加上如下代碼

   public SchoolContext()
{
this.Configuration.ProxyCreationEnabled = false;
}

下面展示下有代理和沒有代理的區別  先看有代理時

 

我們的Administrator 是導覽屬性  我們看到 得到的是一串很長的數字和字母的組合  在下面 訪問這個Administrator屬性時 會通過消極式載入 才得到Administrator屬性

再來看代理關閉時的圖

看我們的導覽屬性 都為null 不能正確獲得導覽屬性

四.自動檢測功能

  • DbSet.Find
  • DbSet.Local
  • DbSet.Remove
  • DbSet.Add
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

在上面的方法中 會調用自動檢測功能。  這個功能預設是開啟的  當我們在做大量操作時 可以關閉這個來提高效能 .例如

using (var context = new UnicornsContext())
{
try
{
context.Configuration.AutoDetectChangesEnabled = false;

// Make many calls in a loop
foreach (var unicorn in myUnicorns)
{
context.Unicorns.Add(unicorn);
}
}
finally
{
context.Configuration.AutoDetectChangesEnabled = true;
}
}

這個自動檢測 在檢測什麼 我還沒自己研究 希望知道的朋友告知下~~

請大家參考這個 MSDN自動檢測的介紹

五.非常好的進一步學習EF的資料

1.Fluent API 的方式定義與資料庫映射

2.利用特性實現與資料庫的映射

3.EF的一些公約的介紹

4.EF團隊部落格

5.Julie Lerman‘s blog

6.EF效能最佳化的一些建議

7.分析EF的資料庫活動

六.總結

原文的內容總算帶上自己的理解 給全寫完了 

以後就是寫寫自己的東西了    下一個寫EF處理樹形結構~~

哦~ 對了   再次貼下 原文的  

MVC3+EF4.1學習系列(九)-----EF4.1其他的一些技巧的使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.