首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架6:将零例外除以

实体框架6:将零例外除以
EN

Stack Overflow用户
提问于 2013-10-07 22:04:11
回答 3查看 1.6K关注 0票数 2

我想在实体框架中实现这样的功能:

代码语言:javascript
复制
db.Customers.OrderBy(c => c.MoneySpent/c.OrdersPlaced)

而不必像这样将任何保护除以零:

代码语言:javascript
复制
db.Customers.OrderBy(c => c.OrdersPlaced == 0 ? 0.0 : c.MoneySpent/c.OrdersPlaced)

为了做到这一点,我尝试了几种方法,但最接近解决问题的方法是禁用ARITHABORTANSI_WARNINGS,我在上下文的构造函数中这样做了:

代码语言:javascript
复制
public class DatabaseContext : DbContext
{
    static DatabaseContext()
    {
        Database.SetInitializer<DatabaseContext>(null);
    }

    public DatabaseContext()
        : base("Name=DatabaseContext")
    {
        Database.ExecuteSqlCommand("SET ANSI_DEFAULTS OFF");
        Database.ExecuteSqlCommand("SET ARITHABORT OFF");
        Database.ExecuteSqlCommand("SET ANSI_WARNINGS OFF");
    }

    // Tables that can be queried directly
    public DbSet<Customer> Customers { get; set; }
}

然后,当我试图从我的Web控制器获得结果时,仍然会得到以下错误:

代码语言:javascript
复制
...failed to serialize the response body for content type 'application/json...
InnerException: Divide by zero error encountered...

当我查看Server发生了什么情况时,似乎每当进行新的查询时,ANSI_WARNINGS就会重置为ON

是否有一种方法可以更改ANSI_WARNINGS的默认值,使其在查询之间保持OFF

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-08 08:28:04

我认为您的问题是,ARITHABORTANSI_WARNINGS命令的范围仅限于事务。

默认情况下,从EF6 Database.ExecuteSqlCommand()开始,如果一个事务尚未出现,将在事务中包装该命令。

您要么必须设置数据库默认值-(并接受所有可能产生的影响!)

可以使用sp_configure的“用户选项”选项为所有连接到服务器的ANSI_WARNINGS设置默认设置。欲了解更多信息,请访问配置(Transact-SQL)

否则,您将不得不使用ef6的改进交易支持管理您自己的连接/事务。

不管是哪种方式,避免编码除以零似乎都是一项艰巨的工作.

参考文献:

处理事务(EF6以后)

警告(Transact-SQL)

票数 2
EN

Stack Overflow用户

发布于 2013-10-08 19:12:12

有了科林的好答案,我就能实现下面的控制器了,现在它运行得非常好!谢谢!

代码语言:javascript
复制
public class CustomersController : ApiController
{
    private readonly CutomerContext _context = new CustomerContext();
    private DbContextTransaction _transactionContext;

    public IEnumerable<Customer> Get()
    {
        _transactionContext = _context.Database.BeginTransaction();

        _context.Database.ExecuteSqlCommand("SET ANSI_WARNINGS OFF");
        _context.Database.ExecuteSqlCommand("SET ARITHABORT OFF");

        var orderedCustomers = _context.Customers.OrderByDescending(c => ((double)c.MoneySpent)/c.OrdersPlaced);

        return orderedCustomers.AsEnumerable();
    }

    protected override void Dispose(bool disposing)
    {
        _context.Dispose();
        if(_transactionContext != null)
            _transactionContext.Dispose();
    }
}
票数 1
EN

Stack Overflow用户

发布于 2013-10-08 07:09:30

在每个查询中看到重置设置的原因可能与EF默认打开和关闭每个查询上的连接有关。您可以通过手动打开连接来覆盖此行为。

无论如何,我同意这听起来不像一个强有力的方法。

处理这个问题的更好方法可能是确保OrdersPlaced为NULL而不是零(x / NULL不会导致错误,但将计算为NULL)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19235594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档