0

目前我正在使用MVC4的Web Api功能構建api,使用EntityFramework 4禁用了延遲加載和代理創建。由於我正在遷移現有的MySQL數據庫,因此我使用了數據庫優先策略。EntityFramework失敗MVC Web API的多個SELECT請求

我的服務器的Windows Server 2012(目前仍然是數據中心RC)與IIS 8和Microsoft SQL Server上運行2012

我覺得我一直有問題的「功能」不類別,但更多來自「表現」類別。在例子中,我有一個Person對象。這個對象有孩子的列表,以及一個城市的對象(與城市的基本信息):

[DataContract(IsReference = true)] 
public partial class Person 
{ 
    public Person() 
    { 
     this.Children = new HashSet<Children>(); 
    } 

    [DataMember] 
    public int ID { get; set; } 
    [DataMember] 
    public int ParentID { get; set; } 
    [DataMember] 
    public int CityID { get; set; } 
    [DataMember] 
    public string Name { get; set; } 
    [DataMember] 
    public int Age { get; set; } 

    [DataMember] 
    public virtual ICollection<Person> Children { get; set; } 
    [DataMember] 
    public City City { get; set; } 
} 

[DataContract(IsReference = true)] 
public partial class City 
{ 
    [DataMember] 
    public int ID { get; set; } 
    [DataMember] 
    public string Name { get; set; } 
    [DataMember] 
    public int Residents { get; set; } 
} 

Note: These classes are generated by EntityFramework/DBContext 

這些類的PersonsController使用,使用HTTPGET檢索從一個人的信息:

public class PersonsController : ApiController 
{ 
    private MyEntities db = new MyEntities(); 

    [HttpGet] 
    public Person Get(int id, bool getChildren = false, bool getCity = false) 
    { 
     Person person = this.db.Persons.SingleOrDefault(p => p.ID == id); 
     if (person == null) 
     { 
      throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); 
     } 

     if (getChildren) 
     { 
      person.Children = this.db.Persons.Where(c => c.ParentID == person.ID) 
     } 

     if (getCity) 
     { 
      person.Customer = this.db.Cities.SingleOrDefault(r => r.ID == person.CityID); 
     } 

     return person; 
    } 
} 

首先,我希望有人能給我一些信息,如果這是在Web Api中使用EntityFramework的正確方法,尤其是創建db對象。我已經閱讀了多篇有關創建所謂的存儲庫類的文章,但我選擇不這樣做。

現在我正在創建這個問題的問題; 當我執行請求以獲取ID爲1的人員的信息時,一切順利。另外GetChildren和getCity參數設置爲true。 (這適用於數據庫中所有可用人員)。 但是,這是在執行一個請求時。當我使用Fiddler在海誓山盟之後快速執行相同的請求時,在幾次請求之後,500錯誤開始出現。然後幾個請求再次運行,然後失敗幾次,等等。

當請求失敗時,它會出現以下錯誤消息之一: 由於還有其他線程正在運行,所以不允許新的事務會議。 或 由於存在處理此事務的未決請求,因此無法執行事務操作。

所以這實際上是說他不能創建一個新的事務,因爲在這個會話中還有其他線程,並且它也不能向事務添加請求,因爲有一個已經準備好的隊列。

希望你明白這真的很煩人,因爲這也可能發生在api上線並被多個用戶同時使用時。

有誰知道如何解決上述錯誤?請檢查我的實施例上面,也許它不是最佳:)

在此先感謝!

回答

0

您可以通過在連接字符串中添加'MultipleActiveResultSets = True'來啓用MARS來解決此問題。您必須啓用MARS的原因是您正在單個連接上執行多個查詢,即DbContext。

替代和更好的方法是不啓用MARS和優化你的行動做這個,而不是執行一個查詢(的EntityFramework eager loading)。這有調用單個查詢比3級的查詢(最壞情況)的優勢。

public class PersonsController : ApiController 
{ 
    private MyEntities db = new MyEntities(); 

    public Person Get(int id, bool getChildren = false, bool getCity = false) 
    { 
     var people = this.db.Persons; 

     if(getChildren) 
     { 
      people = people.Include("Children"); 
     } 

     if(getCity) 
     { 
      people = people.Include("City"); 
     } 

     Person person = people.SingleOrDefault(p => p.ID == id); 
     if (person == null) 
     { 
      throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); 
     } 

     return person; 
    } 
}