POCO, ORM and immutability. How to make them work together?

Let's say I have the following C # class that I want to be immutable. You can only install it using a parameterized constructor.

public class InsulineInjection { private InsulineInjection() { // We don't want to enable a default constructor. } public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) { this.Remark = remark; this.DateTime = dateTime; this.Millilitre = millilitre; } public string Remark { get; private set; } public DateTime DateTime { get; private set; } public Millilitre Millilitre { get; private set; } } 

Now I would like to use ORM to create this POCO. However, as far as I can see, all .NET ORM expects properties to be available, and have a public constructor to be able to create this POCO. So I would have to change my POCO to this:

 public class InsulineInjection { public InsulineInjection() { } public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) { this.Remark = remark; this.DateTime = dateTime; this.Millilitre = millilitre; } public string Remark { get; set; } public DateTime DateTime { get; set; } public Millilitre Millilitre { get; set; } } 

This, however, makes my POCO volatile again. Someone who uses it can simply change any property that is not important.

As far as I can see this, I could solve this in two ways:

  • Write my own level of data access (or modify orm) to be able to create the correct POCO instances using the constructor I created.
  • Create some kind of cartographer. Let ORM create simple DTO objects and use a converter to convert the DTO objects to my POCO at the appropriate time.

I am inclined towards solution 2. Does anyone have an example of how to do this? Or does anyone have a better solution than the ones I described above?

+4
source share
4 answers

Many OR / Ms work as long as there are default constructors and setters (regardless of whether they are public or not, they just have to exist)

So this does not work (without a default constructor):

 public class InsulineInjection { public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) { this.Remark = remark; this.DateTime = dateTime; _millilitre = millilitre; } public string Remark { get; set; } public DateTime DateTime { get; set; } public Millilitre Millilitre { get { return _millilitre; } } } 

or this (no setting for last property)

 public class InsulineInjection { public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) { this.Remark = remark; this.DateTime = dateTime; _millilitre = millilitre; } public string Remark { get; set; } public DateTime DateTime { get; set; } public Millilitre Millilitre { get { return _millilitre; } } } 

While this will work:

 public class InsulineInjection { protected InsulineInjection() { // works with many OR/Ms } public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) { this.Remark = remark; this.DateTime = dateTime; this.Millilitre = millilitre; } public string Remark { get; private set; } public DateTime DateTime { get; private set; } public Millilitre Millilitre { get; private set; } } 
+4
source

Not all .NET ORMs require public ownership of data records. NHibernate supports writing data to private fields or setters. However, you need to follow one of the allowed naming conventions for fields so that it can infer the field name from the property name.

Check out the NHibernate documentation on property mappings , in particular, take a look at the tables. Table 5.1. Access Strategies and Table 5.2. Naming Strategies Take a look at the nosetter access nosetter and choose a naming strategy that matches your coding style.

+2
source

To avoid the constructor using native code, you can use the Deprecated attribute

 [Obsolete("Default constructor only here for the ORM", true)] public InsulineInjection() {} 

Passing true in the attribute will give a compiler error if you really call this constructor.

+2
source

This script is processed initially by dapper-dot-net .

You just need the order and type of the request fields to match the order and type of the constructor arguments. Therefore, for your class, the query will look something like this:

 select millilitre, ,dateTime ,remark from injections 

Unfortunately, dapper will not know how to convert something from decimal to milliliter.

0
source

Source: https://habr.com/ru/post/1445074/


All Articles