0

目前我正在使用 MVC4 的 Web Api 功能构建一个 api,使用 EntityFramework 4 并禁用延迟加载和代理创建。由于我正在迁移现有的 MySQL 数据库,因此我使用了数据库优先策略。

我的服务器在带有 IIS 8 和 Microsoft SQL Server 2012 的 Windows Server 2012(目前仍然是 Datacenter RC)上运行。

我认为我遇到的问题不属于“功能”类别,而更多来自“性能”类别。例如,我有一个 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 上线并被多个用户同时使用时。

有谁知道如何解决上述错误?请检查我上面的实现示例,也许它不是最佳的:)

提前致谢!

4

1 回答 1

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;
    }
}
于 2013-02-10T18:23:37.827 回答