For a complex type in entity framework with only nullable properties, why is that for something like the following requires the complex type be instantiated:
[ComplexType]
public class Address {
public string Address1 { get; set; }
}
public class Customer {
[Key]
public int CustomerId {get;set;}
public Address Address {get;set;}
}
More specifically, if you don't declare and address type, you get a "Null value for non-nullable member. Member: 'Address'." As per this question.
As long as all the properties in the complex type are nullable, why is it that entity framework requires an instance of Address? Since Address1 is nullable, why can it not just assume that and create the table (and column Address_Address1) and null value in the row as if I had created an instance of Address with a null Address1?
Or is there an attribute/fluent setting I can apply to achieve that?
look at this question Entity Framework 5 DbUpdateException: Null value for non-nullable member.
you need to instantiate the complex type even if all the properties are null.
Even if the properties are nullable, the class containing them isn't. You can have Address.Address1 as null, but Address itself has to be instantiated.
Related
I am trying to make a model class in C# in which i require object/List properties as optional property:
public class Customer
{
[JsonProperty("Custid")]
public string CustId { get; set; }
[JsonProperty("CustName")]
public string CustName { get; set; }
}
public class Store
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("Name")]
public string? Name { get; set; }
[JsonProperty("Customer")]
public List<Customer>? Customers{ get; set; } *//Error 1*
[JsonProperty("OtherProperty")]
public object? OtherProperty{ get; set; } *//Error 2*
}
The above code is giving error as :-
Error 1: The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable'
Error 2: The type 'List' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable'
Please Explain me the above scenario and provide me with the alternate solution.
string, List and object are all reference types. Those are nullable by default. The Nullable type (e.g. int? is a shorthand for Nullable<int>) is only used for value types.
In C# 8.0, a new feature was introduced that allows for non-nullable reference types - i.e. reference types that explicitly disallow null assignment. This is an opt-in feature - you can enable it to allow you to more clearly show intent about the references. If you use this, the syntax used to define nullable reference types is the same as for nullable value types:
string nonNullableString = null; // Error
string? nullableString = null; // Ok
Keep in mind that enabling non-nullable reference types means that all of the reference types that aren't followed by ? will be non-nullable; this might require you to make lots of changes in your application.
So there's your two choices. Either enable non-nullable reference types, and then you need to explicitly mark types that you want to have nullable, or stick with nullable reference types, and just use string instead of string? for the same result. I would encourage the use of non-nullable types by default, since it holds some promise for avoiding an entire class of very common programming mistakes.
If you aren't using C# 8:
object? doesn't exists. object is already nullable.
List<Customer>? doesn't exists. List<Customer> is already nullable.
If you want to use nullable reference types you must update your compiler version!
The Nullable<T> type requires that T is a non-nullable value type, for example int or DateTime. Reference types like string or List can already be null. There would be no point in allowing things like Nullable<List<T>> so it is disallowed.
I'm calling the Dapper extended function Query for the IDbConnection class. The problem is, some of the values its returning are NULL in the database. It keeps complaining about them, so I've been converting the members of my return class to nullable types. But I'm thinking I may end up doing this for almost every member, because the data is often incomplete. This is being changed from older code that uses the DataRow class and is able to assign empty values from it to string members of my return class without any problems using just ToString.
public class ProductInfo
{
public Char Department { get; set; }
}
This works:
ProductInfo myProduct = new ProductInfo{};
myProduct.Department = dataRow["department"].ToString();
dataRow["department"] shows as {} and myProduct.Department shows as "".
This gives an exception:
List<ProductInfo> myProduct = new List<ProductInfo>();
myProduct = dbConnection.Query<ProductInfo>(command, parameters).ToList();
Wtih the error: Error parsing column 1 (department=<null>) Details: System.ArgumentNullException: Value cannot be null
Am I missing a step in the process Dapper uses to assign values? Or is extensive use of nullable types standard practice with it?
This isn't a limitation with Dapper; it's how your model is setup.
A char type isn't nullable.
Change your model to char? to make it nullable.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
static void Main(string[] args)
{
Student student = new Student()
{
ID = 12,
Name = "Manu",
LastName = "Shekar"
};
Iregister x = student;
Student newstudent = x as Student;
//Console.WriteLine(x.LastName); //Uncommenting this shows compilation error
Console.WriteLine(newstudent.LastName); //This Show "Shekar"
Console.ReadKey();
}
class Student : Iregister
{
public int ID { get; set; }
public string Name { get; set; }
public String LastName { get; set; }
}
interface Iregister
{
int ID { get; set; }
String Name { get; set; }
}
I wonder how the newstudent.LastName gets the correct value since it is casted from Iregister which doesn't have LastName property?
How the value "Shekar" is passed from student.LastName to newstudent.LastName. Did x stores it somewhere in between? Pardon me if i miss something basics.
You create a single object, and assign a reference to it in the variable student.
You then create a second reference to the same object and assign that to x. Both x and student are referring to the same object, but the type of the x variable means that only the members defined on IRegister are available.
You then create a third reference to the same object and assign that to newstudent. Since newstudent is of type Student, you can access all of the member of Student from that reference.
Not that the variables just store references. It's the object that stores its own actual data, and that object remained unchanged throughout the process.
I wonder how the newstudent.LastName gets the correct value since it
is casted from Iregister which doesn't have LastName property?
The truth is that x is a type Iregister but it's pointing to a Student object hence once casted you're able to access the Student fields.
When using x directly, the compiler allows you to choose only the members defined on IRegister type, because x is of that type. Once you cast x to Student, the compiler allows you to use any member of Student, since the newstudent variable is of type Student.
How Interface stores inherited class's Property
Interfaces do not store values. They only ensure the availability of certain properties and methods in the classes that implement the interface.
I wonder how the newstudent.LastName gets the correct value since it is casted from Iregister which doesn't have LastName property?
Downcasting an object does not change the object's type, it only changes the type of the variable that you're using.
public interface IMyInterface
{
String Name { get; }
}
public class BaseType : IMyInterface
{
public virtual String Name
{
get { return "Base Name"; }
}
}
public class DerivedType : BaseType
{
public override String Name
{
get { return "Derived Name"; }
}
}
I then tested the following commands in the C# Interactive window:
var derived = new DerivedType();
IMyInterface derivedAsInterface = derived;
BaseType derivedAsBaseType = derived;
derived.Name //returns "Derived Name"
derivedAsInterface.Name //returns "Derived Name"
derivedAsBaseType.Name //returns "Derived Name"
As you can see, whenever you ask for the Name property, the object still behaves as a DerivedType, because that is what the object is.
This is because classes are inherently reference types. This does work differently for value types (e.g. float and int), but that has to do with the inherent differences between value and reference types.
If you want to know why, read up on the difference between value and reference types in C#
If you think about it, your assumption does not make sense. In my code example, I have three separate variables: derived, derivedAsInterface, derivedAsBaseType. These all point to the same object in memory.
This logically means that the same object must be compatible with all three variables, otherwise it would be impossible to use all these variables when you want to.
If the object was changed into an object of type IMyInterface, then my variables derivedAsBaseType and derived would no longer function correctly.
If the object was changed into an object of type BaseType, then my variable derived would no longer function correctly.
The only remaining explanation is that my object has always kept its original type (DerivedType), since that is the only way how it can maintain compatibility with all three variables.
If you do not understand why they refer to the same object in memory, you should read up on the difference between value and reference types in C#. This topic is much too broad for an answer on StackOverflow.
In the following code, I pass a struct into a constructor that is expecting a class. Why does this compile and run without error (and produce the desired output)?
class Program
{
static void Main()
{
var entity = new Foo { Id = 3 };
var t = new Test<IEntity>(entity); // why doesn't this fail?
Console.WriteLine(t.Entity.Id.ToString());
Console.ReadKey();
}
}
public class Test<TEntity> where TEntity : class
{
public TEntity Entity { get; set; }
public Test(TEntity entity)
{
Entity = entity;
}
public void ClearEntity()
{
Entity = null;
}
}
public struct Foo : IEntity
{
public int Id { get; set; }
}
public interface IEntity
{
int Id { get; set; }
}
If I change my Main() method so that it includes a call to ClearEntity(), as shown below, it still generates no error. Why?
static void Main()
{
var entity = new Foo { Id = 3 };
var t = new Test<IEntity>(entity);
Console.WriteLine(t.Entity.Id.ToString());
t.ClearEntity(); // why doesn't this fail?
Console.ReadKey();
}
where TEntity : class forces TEntity to be a reference type, but an interface such as IEntity is a reference type.
See here:
http://msdn.microsoft.com/en-us/library/d5x73970(v=vs.80).aspx
where T : class | The type argument must be a reference type, including any class, interface, delegate, or array type
Regarding your second question, you might think t.ClearEntity() would fail because it's assigning null to a variable whose type is a value type, but that's not the case. The compile-time type of Entity is the reference type IEntity, and the runtime type (after assignment) is the null type. So you never have a variable of type Foo but value null.
from the C# documentation:
where T : class
The type argument must be a reference type, including any class, interface, delegate, or array type. (See note below.)
Because you're passing the struct via an interface, it's still considered a reference type.
Within the .net runtime, every non-nullable value type has an associated reference type (often referred to as a "boxed value type") which derives from System.ValueType. Saying Object Foo = 5; won't actually store an Int32 into Foo; instead it will create a new instance of the reference type associated with Int32 and store a reference to that instance. A class constraint on a generic type specifies that the type in question must be some sort of a reference type, but does not by itself exclude the possibility that the type may be used to pass a reference to a boxed value-type instance. In most contexts outside generic type constraints, interface types are regarded as class types.
It's important to note that not only are boxed value types stored like reference types; they behave like reference types. For example, List<string>.Enumerator is a value type which implements IEnumerator<string>. If one has two variables of type List<string>.Enumerator, copying one to the other will copy the state of the enumeration, such that there will be two separate and independent enumerators which point to the same list. Copying one of those variables to a variable of type IEnumerator<string> will create a new instance of the boxed value type associated with List<string.Enumerator and store in the latter variable a reference to that new object (which will be a third independent enumerator). Copying that variable to another of type IEnumerator<string>, however, will simply store a reference to the existing object (since IEnumerator<string> is a reference type).
The C# language tries to pretend that value types derive from Object, but within the guts of the .net Runtime they really don't. Instead, they're convertible to types which derive from System.ValueType (which in turn derives from Object). The latter types will satisfy a type constraint, even though the former ones will not. Incidentally, despite its name, System.ValueType is actually a class type.
I, likewise, assumed that constraint keyword class meant the same class as the type declaration keyword class, but it doesn't.
As explained in the other answers, the term class here is over-loaded, which seems to me to be a horrible decision for the C# language design. Something like referencetype would have been more helpful.
Is it possible when looking at a class' properties to detect if any of them is a reference type.
Take below as an example:
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProgrammeClient
{
public int Id { get; set; }
public bool IsActive { get; set; }
public IClient Client { get; set; }
}
ProgrammeClient: -
Id and IsActive are properties but Client is a reference type. Is there a way of detecting this?
Many thanks,
Kohan.
Addendum
The reason i ask is: I am using a mapper that checks types are the same before matching property names and copying the values. My hope is to detect classes and override the type matching and simply copy the classes properties if the THEY type match.
Well, it sounds like you may be trying to detect the difference between a value type and a reference type. You can find that out using Type.IsValueType... but be aware that value types can easily have properties too. (Think about DateTime for example.) Also, some types which you may want to regard as "not objects" are reference types - string being a prime example.
Another option would be to use Type.IsPrimitive - is that what you're looking for? If so, you should be aware that decimal, DateTime and string are not primitive types.
If you can describe exactly what makes a type an "object" in your way of thinking (or rather, in whatever way makes a semantic difference in what you're trying to do with your type). I suspect you don't currently have a very clear set of criteria - coming up with those criteria may well clarify other aspects of your current task, too.
You can use a little reflection to see if a property is a value type or a class type. Class is probably what you mean by "object". All types in .NET derive from the object type.
Client.GetType().IsClass
Or you can loop through all properties and see which are compound
foreach(var p in ProgrammeClient.GetType().GetProperties())
{
if(p.PropertyType.IsClass) Console.WriteLine("Found a class");
}
Check if the type is a string and check if it is a class.
public static bool IsNonStringClass(this Type type)
{
if (type == null || type == typeof(string))
return false;
return typeof(Type).IsClass;
}
All properties in your example return objects, as everything is an object in .NET; int and bool are objects. If you mean a reference type, as opposed to value types, then you can do the following:
foreach (PropertyInfo pi in typeof(Client).GetProperties()) {
if (pi.PropertyType.IsClass) {
// reference type
// DoMyFunkyStuff
}
}
You can enumerate the properties via Reflection, and check them:
bool ContainsOnlyValues() {
return typeof(ProgrammeClient).GetProperties().All(x => x.PropertyType.IsValueType);
}
The Type.IsvalueType property can reveal this.
Id.GetType().IsValueType
This will be True for Id, false for a class
If using TypeSupport nuget package you can simply do:
typeof(ProgrammeClient).GetExtendedType().IsReferenceType;
TypeSupport does inspection and provides deeper insight on the capabilities of a given type, handling things like strings, enums etc and makes it easier to code these types of things.