Reputation: 588
I red this article: The entity cannot be constructed in a LINQ to Entities query , but guess it's not fully related to my issue.
I have this code:
public class Class1
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
}
[Table("Class2")]
public class Class2
{
[Key]
[Column("Prop1")]
public string Prop1 { get; set; }
[Column("Prop2")]
public string Prop2 { get; set; }
[Column("Prop3")]
public string Prop3 { get; set; }
}
and method edit where I want to use these ones:
using (var data = new Context())
{
var config = data.Class2.FirstOrDefault(c => c.Prop1.Contains(some_string));
if (config != null)
{
config.Prop1 = class1_instance.Prop1;
config.Prop2 = class1_instance.Prop2;
config.Prop3 = class1_instance.Prop3;
}
data.Entry(config).State = EntityState.Modified;
data.SaveChanges();
}
So what I want to get is simplify editing, instead of assigning each property one by one I want to write something like config = class1_instance;
So I've inherited Class1
from Class2
, but getting
System.NotSupportedException
(the entity or complex type "Class1" cannot be constructed in a Linq to Entities query).
How can I handle it?
Upvotes: 0
Views: 243
Reputation: 30474
Now Class1 and Class2 have equal properties. Is that intended, or is this by accident, and might it be that future versions of Class2 have properties that are not in Class1?
In entity framework, the
DbSet<...>
represent the tables of your database. the class in the DbSet represents one row in the table. The columns of your table are the non-virtual properties of the class; the virtual properties represent the relations between the tables (one-to-many, many-to-many, ...)
Class2 represents a database table. If Class1 is supposed to be equal to Class2, then what is the reason for Class1. If this equality is only now, and in future versions they might be different, you'll have to copy the properties one-by-one.
void UpdateValue(string someString, Class1 value)
{
using (var dbContext = new DbContext())
{
Class2 fetchedData = dbContext.Class2.Where(...).FirstOrDefault();
if (fetchedData != null)
{ // data exists. Update the properties
fetchedData.Prop1 = value.Prop1,
fetchedData.Prop2 = value.Prop2,
fetchedData.Prop3 = value.Prop3,
// future version of Class2 may have properties that are not updated
// no need to set state to modified. Entity Framework will detect the changes
dbContext.SaveChanges();
}
}
}
If you are absolutely certain that every Class2
is a special type of Class1
, now and in far future, you might consider to derive Class2 from Class1:
class Class2 : Class1
{
public int Id {get; set;}
... // properties that are in Class2, but not in Class1
}
This means that every non-virtual property of Class1 is represented by a column in the tables with Classes2.
Derivation won't help you, even if you derive, you'll have to copy the properties one by one. If you'll have to do this several times consider to create a function that copies the proper values for you.
Upvotes: 0
Reputation: 205719
Don't inherit the DTO class from the entity class because EF6 will treat the DTO as an entity participating in some of the supported database inheritance strategies.
Instead, use the SetValues(object) of the DbPropertyValues
returned by the CurrentValues
property of the DbEntityEntry
:
Sets the values of this dictionary by reading values out of the given object. The given object can be of any type. Any property on the object with a name that matches a property name in the dictionary and can be read will be read. Other properties will be ignored. This allows, for example, copying of properties from simple Data Transfer Objects (DTOs).
e.g.
Class1 source = ...;
var target = data.Class2.FirstOrDefault(...);
if (target != null)
{
data.Entry(target).CurrentValues.SetValues(source);
data.SaveChanges();
}
Note that the target entity is already attached (tracked) by the db context, so there is no need to set the entry state to Modified
.
Upvotes: 3