Not-Null constraints in POCO Objects - c#

I am currently writing an financial application, and we have a pretty standard customer table. It consists of many mandatory fields, and some optional like Cell/Fax etc.. I'm using NHibernate as a ORM and have all the mappings right. It already works.
I just wonder, how do I "express" in code that a field is not-null without commenting? I have the hbm.xml files that document this, but it's kinda awkward to look at them for things like this.
The other thing that comes to mind is that I don't want the repository to throw NHibernate Exceptions at my Logic, so maybe I should go the validation route in the Controller.
Still, how can I make the POCO code express that some fields can be null?
As you can see, I want to have Cellular and Fax be optional while Phone mandatory. They are all just composite mappings, so the mapping file just specifies that the single elements of each have to be not-null, but I hate to do the Person.Cellular != null check all the time to avoid having a NullReferenceException.

There are a few ways of doing this depending on your POCO behaviour and coding style.
Firstly, you could use nullable types to express that this field is nullable and it would therefore be implicit that the rest are not nullable.
Alternatively you could introduce a Phone value type as the type for the Phone property of the POCO you illustrated, implying that because it is not a primitive type it is "more important" - this would also enable you to encapsulate phone number validation within the class itself.
In my mind, to be a true POCO object, it need not worry about the underlying nullability within the database table it is persited in... it should actually have validation and value types that express its behaviour as a stand alone entity; thus before it gets to NHibernate it is already in a valid state.

Make notnull properties readonly and write to them via a public constructor. Make the default constructor protected or private.
public class DomainObject{
private string nnp;
protected DomainObject(){}
public DomainObject(string nnp){
this.nnp = nnp;
}
public string NotNullProp {get {return nnp;}}
public string NullableProp {get;set;}
}

Related

What is the correct way to handle controller request model validation with nullable reference types?

Say I have a request model object:
public class RequestModel
{
public string? Id { get; set; }
// other properties...
}
And I want to use that model for this example controller method:
public ResponseModel ExampleMethod(RequestModel request)
{
// FluentValidation validator
_validator.ValidateAndThrow(request);
// This method does not accept a nullable type
_dependency.DoSomething(request.Id); // Causes "Possible null reference argument for parameter" error
return new ResponseModel();
}
In this case it's correct for the Id property to be marked as nullable (because in theory the request could not include it). The validator will ensure that the properties are not null. However if I want to use this property in DoSomething() then I will get compiler warnings due to the fact that the Id could be null. The only solution I can find is to map the external request object to some internal version where the properties are not nullable.
However this would require the mapping to essentially be performing validation (by throwing some kind of exception during mapping if a null is encountered) which feels like a violation of separation of concerns:
public ResponseModel ExampleMethod(RequestModel request)
{
// FluentValidation validator
_validator.ValidateAndThrow(request);
// Map the request to an internal object - throw an exception if mapping fails due to null properties
var internalModel = _mapper.Map<InternalModel>(request);
// This method does not accept a nullable type
_dependency.DoSomething(internalModel.Id); // No more error
return new ResponseModel();
}
Not sure if I'm missing something here or if this is the only way to solve the problem. I can't make the property non-nullable as then it would require a default value (eg. empty string, or even worse - null! or default!) which would make it impossible to determine whether the property was missing in the request or was genuinely passed as an empty string. I believe something like this proposal may resolve the issue as then I would be able to indicate to the compiler that I'm expecting these non-nullable properties to be provided upon initialization (by model binding) rather than with a constructor. Am I missing some aspect of nullable reference types here that would make this any easier to deal with?
You have a model with an optional value. Within a user-defined method you validate that this value is defined. The compiler can't determine this behaviour and thous the warning.
To help the compiler you could use the null-forgiving operator like this:
_dependency.DoSomething(internalModel.Id!);
Instead of using allowing null and afterwards check this manually you should maybe use better the available model validation within ASP core. Within your model you should better mark your property with the RequiredAttribute and also manually calling a fluent validator is not needed if you register it within your startup code with .AddFluentValidation(). If your model and validator is correctly marked you can within your Controller method do something like this and you're done:
if(!ModelState.IsValid)
return BadRequest(ModelState);
The only solution I can find is to map the external request object to some internal version where the properties are not nullable.
This sounds like a great approach to me. It's very common to separate request models from your core business models. The role of a controller action (which this appears to be) is largely to coordinate the translation of outside requests to and from the core business logic.
You might even want to have your dependency use your internal model rather than the Id, to avoid primitive obsession. If your dependency "knows" that the number it's being given should represent the Id of a specific type of model, it may be less error-prone to make it impossible for someone to give it a number that has nothing to do with that model type (or an ID directly from an input model that they forgot to validate).
_dependency.DoSomething(internalModel);
However this would require the mapping to essentially be performing validation (by throwing some kind of exception during mapping if a null is encountered) which feels like a violation of separation of concerns
Validation of inputs is an implied part of any method's contract, including any method that returns a value. Does int.Parse() violate separation of concerns by throwing exceptions on bad inputs before returning an int?
If anything, you're violating separation of concerns by using a single model class to represent two different concepts (input versus domain model), which can change for different reasons.
There's only one "concern" involved with validating the input model and converting it into a known-valid domain model. That implies that you should probably separate that concern into its own method/class.
public ResponseModel ExampleMethod(RequestModel request)
{
var internalModel = _requestValidator.Validate(request);
_dependency.DoSomething(internalModel);
return new ResponseModel();
}
The fact that your _requestValidator is using fluent model validation and automapper is an implementation detail that this level of code (a controller action, e.g.) shouldn't have to worry about. Maybe you'll change that some day to use explicit hand-coded mapping. You'd want your unit tests to test that validation/mapping independent of this class's logic.

I'm looking for a way to create new "primitive" types with additional constraints which are visible at coding time to users of the type

Suppose I have an entity in my universe of discourse called a Widget.
Suppose the Widget has an attribute called a WidgetCode. This attribute is defined (by the system of record) to be an alphanumeric value (ie, it's a string) of length exactly 8.
I might implement that in code as follows:
class Widget
{
private string _WidgetCode;
public string WidgetCode
{
get => _WidgetCode;
set
{
if (value.Length != 8) { throw new Exception("length must be 8"); }
_WidgetCode = value;
}
}
}
This is OK, but not ideal. The test in the setter will prevent the property from accepting an invalid value at runtime. But if some other developer wants to make use of my class, then the only way they can find out that the constraint exists is by looking at the implementation of the setter. Which would, of course, violate some pretty fundamental computer science 101 concepts.
In contrast we can look into the world of relational databases. In that world there is a fundamental type. "character", but I can create what is essentially a completely different type when I actually make use of it by specifying the length as part of the type. In the case of a WidgetCode, that would be a char(8). I can add other restrictions as well, in the form of check constraints.
When I do this, I have effectively created a new, more "refined" primitive type, which represents a WidgetCode, and does not represent any arbitrary string value of any arbitrary length.
More importantly, any SQL developer who needs to interact with my schema can see the constraints on my new type. They don't have to go and read separate documentation stored outside the schema. They don't have to live in ignorance of the constraint and hope that they never run afoul of some hidden constraint that they can't see while writing code. The constraint is declared in the schema, and the same thing which implements the constraint also documents it. It is impossible for the "documentation" to get out of synch with the implementation.
This idea doesn't have to be limited to strings. We might want to store a property called Percentage, and declare its domain as a real number between 0 and 1 with scale 3, such that it should not be possible to write the value 1.5 to this property. Once again in a relational schema, that could be a Percentage decimal(4,3) not null check (Percentage between 0 and 1).
Is there any mechanism in C# whereby that same kind of more refined type can be created, and where developers using that type can see the constraint at coding-time without having to go and read some external documentation, hoping that the documentation is up to date?
DataAnnotations get some of the way there, but they are clearly designed to inform users (specifically of GUIs) about a problem with an entered value at runtime. I am looking for a similar kind of tagging which provides the same information to developers making use of the type at coding time.
This question has been answered to my satisfaction through a combination of the comments by Eric Lippert and Matthew.
There is no particular built in language support, nor any particular annotation package, but one possibly functional approach may be to use T4 text templates.

How to Intercept EF operations?

I am currently using Entity Framework for a project and one of my classes have an Enum representing some values.
So far EF is saving the Enums as numbers in the database, but I wanted to save them as their actual string names. For example, the Enum NY is saved as 1, instead of "NY".
I have already seen some ways to make this work, like having a string property with a hidden Enum private field, but I wanted to know if there is a way I can just Intercept EF when it's doing the CRUD operations and then I can change the Enum to a String in the Data Context class.
No, you cannot do that directly: when you map your class with an Enum property, that property is mapped to a database int column, and you cannot change that in any way. I mean that, as you cannot change the model, there is no way to intercept and convert the Enum property value into an string, because the model stubbornly wants an int.
That said, there are several ways to make it work:
having an string property for the key and a [NotMapped] Enum property that updates that key. SEE THE NOTE: But the key must be public, and thus accesible through the application code.
using a class that have only the enum property and is used in your application domain, and a different class which is used for your EF model, and map the values, for example using ValueInjecter or Automapper
I usually take the first path and use an attribute that allows me to define the string key for each Enum value, so you can reuse this pattern in all the cases in which need to do this.
NOTE: this part of the answer was wrong: you can map any property regardles of the modifier (public, protected, private, internal...). EF conventions only include the public properties, and there are no data annotations that can overcome this limitation. But you can use it with the Fluent API. However, as the property is private,you cannot access it directly using the Fluent API. There are several solutions to do it described here: Code First Data Annotations on non-public properties
If you follow this path, you can have a class like this:
public class MyEntity
{
// ...
[NotMapped]
public EnumType Value
{
get { /* return KeyForEnum converted to EnumType value */ }
set { /* set KeyForEnum value from the received EnumType value*/}
}
// Use some mechanism to map this private property
private string KeyForEnum { get; set; }
// ...
}
As you can see, if you use a class like this, in the app the entity will have a property of EnumType type, but in the database it will be an string.
One of the tricks to be able to map it through Fluent API is this:
1) Add an static property that returns an expression able to select the property from an object of this class, i.e.
public static readonly Expression<Func<MyEntity,string>> KeyForEnumExpression
= me => me.KeyForEnum;
2) Use it in the fluent API to get the property mapped, like so:
modelBuilder
.Entity()
.Property(MyEntity.KeyForEnumExpression)
LAST NOTE: This will modify the POCO class by adding the static readonly property. You can use Reflection instead to build an expression to access the private property, like you can see here: EF 4.1 Code First, ¿map private members?. It's in Spanish, but you can look directly at the code

What fields and properties should I serialize?

I do not think this is a duplicate. I have done some reading but did not find anything the same as this. It seems that fields can be serialized in binary formatters and in protobuf but not in XML. I don't know about JSON.
I am looking at replacing the standard .NET binary serializer with protobuf-net. The reason is to improve speed and get a smaller persisted file size.
In NET Binary I just marked the classes as serializable and left it at that. Not good I suspect.
With protobuf-net I need to specify what gets serialized with the [ProtoMember()] attribute. My newbie testing shows that private fields get serialized if so marked as do auto properties.
I do not want to change the class code definitions at all since I still need to be able to deserialize the old persisted data created by the NET serializer. I have a mixture of:
Private fields that get used inside the class
Private fields whose value gets set in constructors
Private fields that are backing fields for non automatic properties
Properties with the backing fields above
Auto properties
Properties with no setters that return some calculation or value determined internally
and probably some others. In other words pretty much every type of field and property.
I guess I need to persist any value that represents the state of the object that cannot be constructed after deserialization from the file.
I suppose there would be no harm in persisting every field and property but that would just make the job slower and the file bigger than it needs to be.
I think I can ignore private fields that are used only inside the class and are not set from outside.
I think I should persist those fields that are set in constructors.
I am not sure about backing fields - is it better to persist them or their public property?
I must persist auto properties
I can't persist properties with no setters so I need to persist whatever fields/properties get used in their calculations.
Am I on the right track or missing the point.
Thanks in advance.
We can't say what needs to be serialized. BinaryFormatter works on an "all fields" basis (unless they are explicitly marked not for serialization). You could use the same approach, but if you're using automatically implemented properties (which is fine) then note that you cannot add attributes to the backing field - unlike field-like events, the following is not valid c#:
[field:ProtoMember(1)] // not valid
public int X { get; set; }
This means that your only sensible choice is to decorate the property:
[ProtoMember(1)]
public int X { get; set; }
Because, if you change the automatically implemented property to a regular property, you will have broken BinaryFormatter's deserialization, since the field-name will have changed. That's fine, though - there's nothing wrong with marking either the fields or the properties (or both in the same type) for serialization. Another consideration on some platforms is accessibility: a private field may be inaccessible, where-as a public field works fine. And obviously public fields are pretty uncommon.
So:
decide what needs to be serialized (I can't tell you this)
mark it for serialization
do not change anything from automatically-implemented property to a regular property if you need BinaryFormatter to keep working (protobuf-net doesn't care if you change this)

Should I use values or keys?

I am warpping an ArcGIS IFeature object with a class that has my required properties to get and set them easily.
Basically, the get and set operations just use feature.get_value(index) and feature.set_value(indes, value), and expose the strongly typed value.
I have several fields that use a domain (basically, an IDictionary<string, object>) to represent common properties across the application.
At first I figured I would only use the keys of the domain (which are normal int values) in my wrapping class, and use the domain in my ToString() method, to translate to strings for the UI.
Later I figured out I can use strings in my applicaiton (which makes it easier to pass around nulls, as the actual domain fields are nullable most of the time), and only change those fields' getters and setters to use GetDomainValue(index) and SetDomainValue(index, value) method that will translate between the key and value to/from the underlying feature object.
What approach do you think is better? I figured the string approach is a bit more "persistent ignorant", as my class doesn't care how the values are being saved, just their string representation.
On the other hand, it makes the code jump through loops a bit - instead of returning what's in the feature, every getter needs to iterate the domain.
You might want to think about representing your domain fields with Nullable< Int32>. This would give you a way to represent features that have a domain value specified but it also allows you to directly specify null where appropriate.
I ended up sticking with the domain values, so that I can also verify that the calling code passed a valid value.

Categories