为什么签名负数(十进制)在Linq / Lambda中转换为无符号?

时间:2015-03-18 17:10:57

标签: c# linq decimal code-first

我有一个名为Transactions的表,数据如下:

SELECT [ID]
  ,[DateTime]
  ,[AccountID]
  ,[Type]
  ,[Amount]
FROM [TestModelDb].[dbo].[Transactions]

输出:

ID  DateTime    AccountID   Type    Amount
1   2015-03-17  1           0       10.00
2   2015-03-17  3           0       20.00
3   2015-03-17  1           0       100.00
4   2015-03-18  1           1       -10.00
5   2015-03-18  3           1       -5.00

我正在使用Code-First。当我进行简单查询时,金额列中的所有十进制数都是无符号的:

IEnumerable<decimal> test = Transactions.Select(t => t.Amount);
foreach (decimal amount in test)
{
    Debug.WriteLine("Amount: " + amount);
}

在输出框中显示:

Amount: 10.00
Amount: 100.00
Amount: 10.00
Amount: 20.00
Amount: 5.00

为什么linq或lambda查询会丢弃符号?

更新#1

交易类:

public partial class Transaction : EntityBase
{
    public Transaction()
    {
        DateTime = DateTime.Now;
    }

    /// <summary>
    ///     Gets or sets the date time.
    /// </summary>
    /// <value>The date time.</value>
    public DateTime DateTime { get; set; }

    /// <summary>
    ///     Gets or sets the account identifier.
    /// </summary>
    /// <value>The account identifier.</value>
    public int AccountID { get; set; }

    /// <summary>
    ///     Class Transaction.
    /// </summary>
    /// <summary>
    ///     Gets or sets the account.
    /// </summary>
    /// <value>The account.</value>
    [ForeignKey("AccountID")]
    public Account Account { get; set; }

    /// <summary>
    ///     Gets or sets the type.
    /// </summary>
    /// <value>The type.</value>
    [Required]
    public TransactionType Type { get; set; }

    private decimal _amount;

    /// <summary>
    ///     Gets or sets the amount.
    /// </summary>
    /// <value>The amount.</value>
    public decimal Amount
    {
        get { return _amount; }
        set
        {
            decimal temp;
            if (Type == TransactionType.Withdrawal)
                temp = value*-1;
            else temp = value;
            _amount = temp;
        } 
    }
}

我的DbContext:

public class TestContext : DbContext
{
    public TestContext()
        : base("name=TestContext")
    {
    }

    public DbSet<Person> People { get; set; }
    public DbSet<Account> Accounts { get; set; }
    public DbSet<Transaction> Transactions { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    }
} 

2 个答案:

答案 0 :(得分:1)

我的猜测是您的交易类型被标记为提款,因此您的代码在此处将数字从负数转为正数:

if (Type == TransactionType.Withdrawal)
                temp = value*-1;

答案 1 :(得分:1)

实体框架在从数据库调用中对对象进行水合时,会对每个属性使用setter。换句话说,在构建对象时,它将Amount设置为-10,但由于它是“撤销”,因此该代码(正如Robert指出的那样)将值重新转换为正值:

if (Type == TransactionType.Withdrawal)
            temp = value*-1;

尝试将其更改为:

if (Type == TransactionType.Withdrawal && value > 0)
            temp = value*-1;

另外,正如罗伯特评论的那样,var t = new Transaction(); t.TransactionType=Withdrawl; t.Amount=50;var t = new Transaction(); t.Amount=50;t.TransactionType=Withdrawl;给出了不同的结果,这是非常危险的。

您应该使Transaction类型不可变,或者至少需要构造函数中的类型。如果你那样做,那就知道EF需要一个无参数的构造函数。幸运的是,它通过Reflection找到它,因此您可以将该构造函数设为私有。