2

私はエンティティフレームワークでこのようなものを作りたいと思っています:

db.Customers.OrderBy(c => c.MoneySpent/c.OrdersPlaced)

次のようなゼロ保護による除算を行う必要はありません。

db.Customers.OrderBy(c => c.OrdersPlaced == 0 ? 0.0 : c.MoneySpent/c.OrdersPlaced)

それを行うために、いくつかのことを試しましたが、問題を解決するのに最も近かったのは、コンテキストのコンストラクターで実行したARITHABORTandを無効にすることでした。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 API コントローラーから結果を取得しようとすると、まだ次のエラーが発生します。

...failed to serialize the response body for content type 'application/json...
InnerException: Divide by zero error encountered...

SQL Server Profiler で何が起こっているかを調べてみると、新しいクエリが作成されるたびに にANSI_WARNINGSリセットされているように見えます。ON

SQL Server プロファイラー

クエリ間ANSI_WARNINGSでとどまるように、おそらくデフォルト値を変更する方法はありますか?OFF

4

3 に答える 3

1

Colin の素晴らしい回答により、次のコントローラーを実装することができました。今では完全に正常に動作します。ありがとう!

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-08T19:12:12.500 に答える