我想在实体框架中实现这样的功能:
db.Customers.OrderBy(c => c.MoneySpent/c.OrdersPlaced)而不必像这样将任何保护除以零:
db.Customers.OrderBy(c => c.OrdersPlaced == 0 ? 0.0 : c.MoneySpent/c.OrdersPlaced)为了做到这一点,我尝试了几种方法,但最接近解决问题的方法是禁用ARITHABORT和ANSI_WARNINGS,我在上下文的构造函数中这样做了:
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控制器获得结果时,仍然会得到以下错误:
...failed to serialize the response body for content type 'application/json...
InnerException: Divide by zero error encountered...当我查看Server发生了什么情况时,似乎每当进行新的查询时,ANSI_WARNINGS就会重置为ON。

是否有一种方法可以更改ANSI_WARNINGS的默认值,使其在查询之间保持OFF?
发布于 2013-10-08 08:28:04
我认为您的问题是,ARITHABORT和ANSI_WARNINGS命令的范围仅限于事务。
默认情况下,从EF6
Database.ExecuteSqlCommand()开始,如果一个事务尚未出现,将在事务中包装该命令。
您要么必须设置数据库默认值-(并接受所有可能产生的影响!)
可以使用sp_configure的“用户选项”选项为所有连接到服务器的ANSI_WARNINGS设置默认设置。欲了解更多信息,请访问配置(Transact-SQL)。
否则,您将不得不使用ef6的改进交易支持管理您自己的连接/事务。
不管是哪种方式,避免编码除以零似乎都是一项艰巨的工作.
参考文献:
处理事务(EF6以后)
警告(Transact-SQL)
发布于 2013-10-08 19:12:12
有了科林的好答案,我就能实现下面的控制器了,现在它运行得非常好!谢谢!
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();
}
}发布于 2013-10-08 07:09:30
在每个查询中看到重置设置的原因可能与EF默认打开和关闭每个查询上的连接有关。您可以通过手动打开连接来覆盖此行为。
无论如何,我同意这听起来不像一个强有力的方法。
处理这个问题的更好方法可能是确保OrdersPlaced为NULL而不是零(x / NULL不会导致错误,但将计算为NULL)。
https://stackoverflow.com/questions/19235594
复制相似问题