Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a c# decimal match a SQL decimal for EF change tracking?

To avoid touching changeless records in EF it's important that original and current entity values match. I am seeing a problem with decimals where the EF entity has SQL representation and that is being compared to c# decimal.

This is debug output from entities with changes detected. This shows the problem pretty clearly. Even though both the entity and the source data are in of type decimal the values are considered difference even though they are equal.

enter image description here

How can I ensure that original and current values match when using c# decimal?

Maybe there is a way to turn the c# decimal into an entity (SQL) decimal before the update?

Another Example

enter image description here

I would expect the truncation to ignore the fact that the incoming precision is higher than the SQL scale

like image 859
jwrightmail Avatar asked Feb 14 '18 02:02

jwrightmail


People also ask

What material is used for AC?

There are several materials which are commonly used as part of the construction of an air conditioner, including plastic, copper, aluminium and stainless steel.

How is AC made?

An air conditioner is made up of a condenser, an inside compressor, an outside compressor, copper pipes, a fan, and controls. Once these are all available, the unit is assembled. First the condenser and inside compressor, then the copper wires that connect them to the fan and outside compressor.

Can we make AC from fridge?

You can fan yourself with the door to cool yourself down, but you can't actually lower the temperature of the room. This is because refrigeration is not a perfectly efficient process. More heat enters the room through the exhaust vent than is extracted from the inside of the refrigerator.

How do I write a simple C program?

The simplest way to get started is to install an IDE (a program for writing code) and a C compiler, and then experiment with some sample code. This wikiHow article will teach you how to write a basic C program that displays a string of text on the screen. Install an Integrated Development Environment (IDE).

How do I create C and C++ programs in Linux?

In order to create C and C++ programs you must have a C/C++ compiler installed on your operating system. If you don't have a compiler installed on your system, please consult the appropriate method for installing the GNU C/C++ compiler on your Linux system.

How do I create a new project in C++?

Select File > New > Project, then select C++, Windows, Desktop, then select empty project in the new project menu. Then click on the folder called "Source" and press Ctrl+Shift+A, then in the new item selection, find the box at the bottom of the dialog, then name it .c.

How do I start programming with a C compiler?

This usually involves opening your IDE for the first time and telling it where it can find your C compiler (if it doesn't come with its own). Some IDEs know where to look for a C compiler on a computer, while others may need your assistance. Once your IDE knows where to find the compiler, you'll be ready to write your first program.


2 Answers

You could implement a proxy-property which handles the conversion from code-precision to db-precision:

public class MoneyClass
{
    [Column("Money")]
    public decimal MyDbValue { get; set; } // You existing db-property

    [NotMapped]
    public decimal MyCodeValue // some property to access within you code
    {
        get
        {
            return this.MyDbValue;
        }
        set
        {
            decimal newDbValue = decimal.Round(value, 2);
            if (this.MyDbValue != newDbValue)
            {
                Console.WriteLine("Change! Old: {0}, New: {1}, Input: {2}", this.MyDbValue, newDbValue, value);
                this.MyDbValue = newDbValue;
            }
        }
    }
}

static void Main(params string[] args)
{
    MoneyClass dbObj = new MoneyClass()
    {
        MyCodeValue = 123.456M
    };

    Console.WriteLine(dbObj.MyDbValue);
    dbObj.MyCodeValue = 123.457M; // won't change anything
    Console.WriteLine(dbObj.MyDbValue);
    dbObj.MyCodeValue = 123.454M; // will change because of 3rd decimal value 4
    Console.WriteLine(dbObj.MyDbValue);
    dbObj.MyCodeValue = 123.46M; // will change
    Console.WriteLine(dbObj.MyDbValue);
}
like image 97
kara Avatar answered Sep 29 '22 07:09

kara


This answer is not supposed to fix exactly the issue you have, but to go around it.

I suggest to code the logic that decides whether an objects needs to be saved or not on a higher application layer (in that respect I consider the EF generated classes as low level objects).

The code which retrieves and stores data could be implemented in a repository class, i.e. a class that manages your data access logic. So what you application uses would be this repository class and not the EF code. Whether the repository class internally uses EF or something else would not be important anymore for you application. If you define an interface for you repository class you could even replace it easily with some or technology to save and retrieve data.

See here for an article from microsoft about the repository pattern. This is an info from a question here at stackoverflow.

I generally would not recommend to use the EF generated classes in normal application code. It might be tempting a first, but also cause problems later as in your case.

like image 43
Martin Avatar answered Sep 29 '22 07:09

Martin