How to assign null to sql entity columns - linq

I have generated linq to sql entites but cannot figure out how to assign null to a nullable column. whenever i try to assign null to it it says "there is no implicit type conversion between int and ". BTW the type of the field is int? and the database column is also nullable.

Try to assign it System.DBNull instead

It seems as though the column isn't really nullable. Check the properties of the column and see that it really is marked as nullable. If it isn't, check your database model and try to recreate the LINQ to SQL model if it's nullable in the database.
Mind that you can't simply mark it as nullable in the LINQ to SQL model and not in the database, since these kinds of discrepancies may cause your LINQ to SQL model to stop working.
Post edit update: I can see that the field type is int? which is the same as Nullable<int> so there shouldn't be a problem to set it to null. However, when getting the integer value, you should use the Value property of the int?. Is that the problem?

Usually I've had to use DBNULL.Value when assigning or comparing a database value to null.

You only need to assign then entites nullable property to null. I've never had to assign or test against System.DBNull when using linq-to-sql entities.
It sounds like the generated entity classes have been manually modified or are out of date from the database.
For your reference, the following is a nullable and a non-nullable integer field:
private int? _someID;
/// <summary>
/// Gets or sets the SomeID.
/// </summary>
[Column(Name="SomeID", Storage="_someID", DbType="INT", UpdateCheck=UpdateCheck.Never)]
public int? SomeID
{
private int _someOtherID;
/// <summary>
/// Gets or sets the SomeOtherID.
/// </summary>
[Column(Name="SomeOtherID", Storage="_someOtherID", DbType="INT NOT NULL", CanBeNull=false, UpdateCheck=UpdateCheck.Never)]
public int SomeOtherID
{
Check your generated entity looks something like the above.

You wrote 'the type of the field is int?'.
I guess this is the problem: the type of the field should be int (without the ?), and the property 'allow null value' should be set to true.
In the designer you can change the field type to int? instead of int and 'allow null', but you run into all kind of trouble this way (as you might have noticed).

It is when you're trying to explicitly create a DB set with a nullable column in an entity.
new Nullable() is what you're looking for.
someEntity newEntity = new someEntity()
{
aNullableInt = new Nullable<Int32>()
};

Related

Servicestack Ormlite multi-column constraint fails where constraint includes Enum

I am using ServiceStack.Ormlite, and also make heavy use of the automatic handling of enums whereby they are stored in the db as strings but retrieved and parsed nicely back into Enums on retrieval, so I can do easy type-comparison - say, for a property "UserRole" in the db/table class "User" of enum type "UserRoleEnum" (just for demonstration).
This works great.. until I want to use the enum property to define a multi-column unique constraint
CompositeIndexAttribute(bool unique, params string[] fieldNames);
like:
[CompositeIndex(true, nameof(UserId), nameof(UserRole)]
public class User
{
public long UserId {get;set;}
public UserRoleEnum UserRole {get;set;
}
(as per :
How to Create Unique Constraint with Multiple Columns using ServiceStack.OrmLite? ).
At which time i get:
System.Data.SqlClient.SqlException
Column 'UserRole' in table 'User' is of a type that is invalid for use as a key column in an index.
I currently see options as:
a) Define UserRole as a string (isntead of UserRoleEnum ) in the table entity class and lose the Enum use.... having to manually test the value each time to confirm that the db value is one that i expect in my business logic later
b) Continue to use UserRoleEnum but lose the ability to declare multicolumn uniqueconstraints using the class attribute, and probably have to create these manually using a subsequent db migration script?
Is there any way to make the enums and the multicolumn constraint play nicely, out of the box?
This issue was because enum properties were using the default string definition fallback of VARCHAR(MAX) which SQL Server doesn't let you create indexes on whereas the column definition of a string property is VARCHAR(8000).
This issue is now resolved from this commit which now uses the VARCHAR(255) string definition of the EnumConverter Type Converter. This change is available from v4.5.5 that's now available on MyGet.
Otherwise you can also change the size of the column definition to match a string property by adding a [StringLength] attribute, e.g:
[CompositeIndex(true, nameof(UserId), nameof(UserRole))]
public class User
{
public long UserId { get; set; }
[StringLength(8000)]
public string UserRole { get; set; }
}

Why model validation is not working

I have following Model class that is used during the Web API Post. As you can see Id field is annotated as Required.
public class Model
{
[Required]
public Guid Id { get; set; }
}
The Post for API is as follows
[HttpPost]
public IActionResult Post([FromBody]Model value)
{
if (!ModelState.IsValid)
return BadRequest();
Model newModel = new Model() { Id = value.Id };
return Ok(newModel);
}
On a sunny day, this is what I see. All good
enter image description here
On a rainy day, when Id is not provided, I get following.
enter image description here
Given that in the second example, a Required field is not provided, shouldn't a BadRequest is returned rather than a 200 with invalid id guid with 00000000-0000-0000-0000-000000000000?
Using the Required annotation
In the Web API Docs, your issue is known as 'under-posting'.
The issue is that Guid has a default value, so when no value is provided, it is initialized with the default value... which then satisfies the Required constraint.
To prevent this, counter-intuitively you make the Guid nullable using Guid?.
Then if the value is not provided, the deserializer will set the value to null, which will cause the Required constraint to be violated.
If the value is provided, it will be set, and all will be well.
See https://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api for more details, there is an example of a similar issue for a decimal property.
The key distinction to understand is that Guid.Empty is really a valid Guid. The only way to distinguish between the user providing a Guid (which is empty) and not providing one at all is to make it nullable, so null = not provided, and Empty = the user provided the empty Guid.
Using a Custom Annotation
If you really don't want to make your Guid nullable, you need to consider what would you do for a 'normal' value type, e.g. an integer. Rather than making it required, you'd use a Range attribute and specify that it must be > 0.
Similarly for Guids, you'd ideally have an attribute that would simply test that it is != Guid.Empty
See https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation#custom-validation for guidance on creating a custom validation atribute.

Why is my Enitty.Contains(attributeField) returning false when I am able to set the value?

I have a block of code that is not working as I thought it would.
I have set an Entity up as follows and have a previous guid.
parentEnt = new Entity("vehicle_ent");
parentEnt.id = guid;
Now when I do a check with a statement:
if (parentEnt.Contains("attribute_field")) {
parentEnt["attribute_field"] = "test";
}
The above will never be called because the if statement fails.
However, if I remove the if statement. I am able to actually assign and run the code:
parentEnt["attribute_field"] = "test";
Is there something I am missing with the Contains Method? I thought it was used to check if the Entity contains the attribute?
On the Entity class, you can always assign an attribute like the example you provided whether or not it exists. If it exists, it will overwrite it (which is what you discovered).
So
parentEnt["attribute_field"] = "test";
Will always work, whether or not the attribute already has a value assigned.
When you run the constructor for a CRM entity object, and assign it a guid
Like
Entity parentEnt = new Entity("vehicle_ent");
parentEnt.id = guid;
you are creating a new object of the entity type with the 'vehicle_ent' logical name and a id of 'guid' At this point all the attribute/properties that belong to an entity with that name, are not created along with the entity object, and you only have an Entity class object with a LogicalName and id set.
If you want to check if an entity record with that id contains a certain attribute, you need to fetch is from the database, using your the organization service, like
ColumnSet attributes = new ColumnSet(true);
parentEnt = _service.Retrieve("vehicle_ent", guid, attributes);
After the retrieve is called you can check if the entity record contains the attribute you need to check.
I just add a couple of things:
The syntax entity[attributename] and entity.Attributes[attributename] are equivalent, the reason can be found inside the Entity metadata:
public object this[string attributeName] { get; set; }
the method maps at entity level the Attributes property (the type of this property is AttributeCollection an inherit from DataCollection<string,object> and the base type is an IEnumerable<KeyValuePair<TKey, TValue>>)
DataCollection contains this method:
// Summary:
// Gets or sets the value associated with the specified key.
//
// Parameters:
// key:
// Type: TKey. The key of the value to get or set.
//
// Returns:
// Type: TValue The value associated with the specified key.
public virtual TValue this[TKey key] { get; set; }
this method adds the key (our attributename) inside the collection if the key is not present before. For this you can assign a value to an attribute without using the Contains method first. Of course when you read the value you need to check if the key is present, this is the purpose of the Contains method, but to read the values the GetAttributeValue can be used as well (but it's necessary to pay attention to the default values returned when the attribute is not inside the collection)

Unable to get name from EntityReference

I'm using CRM 2015 SDK for my plugin. I want the attributes of entity reference in my code. I'm able to get the Guid and Logical Name. But the name returns null for all the entity reference fields. Here is my code:
EntityReference centre= ((EntityReference)quoteEntity.Attributes["mc_centre"]);
Guid centreGuid = centre.Id; //returns Guid
string centreName = centre.Name; //returns null
I have checked the Referenced Entity, "Centre" which uses the 'name' field and has valid value. Has anyone faced the same issue? Am I doing something wrong in my code? I don't want another service call to get the name btw.
the Name property of an EntityReference is not always populated when you cast it from an attribute.
You need to do an additional retrieve if you want to get the name.
This is the relevant MSDN article: EntityReference.Name Property
This property can contain a value or null. This property is not
automatically populated unless the EntityReference object has been
retrieved from the server.
Entity member = service.Retrieve("new_vendor", ((EntityReference)entity["new_vendorname"]).Id, new ColumnSet(true));
or
Entity member = service.Retrieve("new_vendor", Vendor.Id, new ColumnSet(true));
String VendorName = member.Attributes["new_name"].ToString();

MVC3 Required validation, choose value for empty

I have a hidden field which is bound to a int Id in the model, it has a required attribute and some fancy ajax code to set the id client side, the problem is that zero should be acounted as empty. Now the validation will succeed even if no Id has been selected, bow can I set which value should be counted as empty? I hope i do not need to create a custom validator for it.
Thanks
It doesn't maker sense to add required attribute to a non nullable type such as Int32. Value types are always required. You could use a nullable integer instead:
[Required]
public int? SomeProperty { get; set; }

Resources