How to delete child entities in an InverseProperty relationship using code first entity framework 4.1 - ef-code-first

I have a model and I am having trouble managing the relationships using entity framework 4.1
Here the model (simplified):
public class UserConfig {
[Key]
[Column("id", TypeName = "bigint")]
public long Id { get; set;}
[InverseProperty("UserConfigId")]
public virtual List<ColumnConfig> ColumnConfigs { get; set; }
}
public class ColumnConfig {
[Key]
[Column("id", TypeName = "bigint")]
public long Id { get; set; }
[Column("user_config_id", TypeName = "bigint")]
public long UserConfigId { get; set; }
[Column("width", TypeName = "int")]
public int Width{ get; set; }
[Column("col_name", TypeName = "varchar")]
public string ColumnName{ get; set; }
}
The model represents a user and a custom view of a table of data within a UI. They resize the columns the way they want and then save their settings. I have a webservice that accepts a list of the columns they want and their respective widths.
The problem I am having is updating the user's ColumnConfigs within my web service. The webservice does not receive the ColumnConfig id's, so my approach has been to try and first delete all the existing ColumnConfigs for the user, and then second create a new set of objects according to the new values passed in.
I can't manage to delete any of the ColumnConfig objects. Here's my code:
public void UpdateUserConfig(UserConfig uc) {
UserConfig origUserConf = ctx.ColumnConfigs.Find(new object[] {uc.Id});
origUserConf.ForEach(uc => ctx.ColumnConfigs.Remove(uc)); // remove old
origUserConf.ColumnConfigs = uc.ColumnConfigs; // add new
ctx.SaveChanges();
}
This isn't working, it gives the error:
System.InvalidOperationException: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
I'm not sure why is thinks there is a null constraint here. I haven't specified any fields as being required.

The easiest way to remove child relationships would be to invoke:
origUserConfig.ColumnConfigs.Clear();
Unfortunately, this wouldn't work for you for two reasons: (1) You have a non-nullable relationship defined between your Parent and Child entity, and (2) even if the relationship was defined as nullable it would orphan the child rather than deleting it.
Read this article (Deleting Foreign Key Relationships in EF4) to get an idea of how EF handles deleting child entities. In your case you fall under case number 1.
As far as the error you're getting change your foreach to use the ForEach method off the List<T> class:
origUserConf.ColumnConfigs.ForEach(col => ctx.ColumnConfigs.Remove(col))

Related

Why do I need HashSet in many-to-many relation?

I have found many tutorials that use HashSet ex
this.Supplier = new HashSet<supplier>();
In many-to-many relation. But som tutorials use the code below without HashSet (no more or less)
public partial class Product
{
public Product()
{
this.Supplier = new HashSet<supplier>();
}
public long ProductID { get; set; }
public string ProductName { get; set; }
//navigation property to Supplier
public virtual ICollection<supplier> Supplier { get; set; }
}
public partial class Supplier
{
public Supplier()
{
this.Product = new HashSet<product>();
}
public long SupplierID { get; set; }
public string SupplierName { get; set; }
// navigation property to Product
public virtual ICollection<product> Product { get; set; }
}
When I tested the code above and deleted
public xxxx()
{
this.xxxx = new HashSet<xxxx>();
}
I still got an association table and a many-to-many relation.
Why do I need HashSet?
Usually many-to-many relationship defined with ICollection in both table models:
public virtual ICollection<supplier> Supplier { get; set; }
public virtual ICollection<product> Product { get; set; }
The presence of ICollection on models means that lazy loading is enabled, allowing EF to create derived classes for them.
About the use of HashSet inside model generations, ChrisV said in HashSet in EF many to many:
HashSet implements a hash table that is very efficient for a lot of
operations, for instance searching a large set for a single item.
The usage of HashSet by default primarily based on efficiency reasons besides of non-null value, such like Yuval Itzchakov said in Entity Framework:Why the collection type of entity class need to be instanced in the default constructor?:
A HashSet is used because it guarantees that two values which are
equal to each other (which are equality checked by looking at their
GetHashCode and Equals methods) only appear once in the collection.
And yes, you can change the concrete type to any type which implements
ICollection<T>.
The explanations above can be summarized as "HashSet is initialization step of ICollection interface inside model's constructor which guarantees equality between each related model members". EF itself doesn't care what implementations should be apply on ICollection for table models, you can use List<T> in constructor replacing HashSet<T> and many-to-many relationship still doesn't affected.
Inside your template model (.tt file), you may see these lines to generate HashSet<T> by default as it implements ICollection:
foreach (var navigationProperty in collectionNavigationProperties)
{
#>
this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
}
You may doing experiments by removing or changing HashSet<T> initialization when the model is re-generated, however I considered not a good practice to remove it for large amount of data operations.

No key defined. Define the key for this EntityType when implementing interface that has Id

I want to implement an interface defined in Dev Express IResource in my EF Code First business object.
public class JResource : IResource , IXafEntityObject
{
[Key]
public int IdKey { get; set; }
[NotMapped]
public object Id => IdKey; // since IResource wants this.
// other properties
}
When I run my application to create the database I get an error that I need to define the key for this EntityType.
I think the problem is that EF wants to regard Id as the Key but I have made Id NotMapped since I want it to be an Int and the interface wants it to be an object.
Is there a work around?
It turned out that I was using the wrong reference for the [Key] attribute.
The correct one is
System.ComponentModel.DataAnnotations.KeyAttribute

Entity Framework 4 (using EDMX), how to add a field into to model that DB does not have the field actually

I need to add a field into model that Database does not have the field actually.
Because, firstly I tried to add the field into Entity class only.
public partial class Weborder
{
(Auto Generated)
public int orderno {get; set;}
.
.
.
(Add Manually)
public string newField1 {get; set;} //this is new field that DB does not have
public string newField2 {get; set;} //this is new field that DB does not have
}
and later, when I update EDXM then EDMX remove the new fields because the database does not have the field. :(
So I add the field into EDMX model manually. (Add -> Scalar Property)
then an error occur while compiling, the error message say :
Error 1 Error 3004: Problem in mapping fragments starting at line 399:No mapping specified for properties ...
An Entity with Key (PK) will not round-trip when:...
Anybody know how to add new fields into entity class ?
Thank you!
EDITED FOR :
If your model is a representation of your database and in the database you don't have the field, why do you want to add it manually?
=>
When retrieve data, the return type of object is the entity class.
and before passing data from controller to view, I need to add more data(fields) into the IQueryable result.
ex)
public DbSet<WEBORDERLN> WEBORDERLNs { get; set; }
//repository
public IQueryable<WEBORDERLN> WebOrderLns
{
get { return context.WEBORDERLNs; }
}
and now I get the weborderln data in controller. and before passing view, I need to
add extra data into the result.
var data = webOrderLnRepository.WebOrderLns.Where(e => e.PICKNO == OrderNo).ToList();
foreach (WEBORDERLN weborderln in data)
{
weborderln.[NEW FIELD] = "EXTRA DATA"; //// FOR THIS, I NEED TO ADD NEW FILED INTO ENTITY CLASS
}
//return data
I hope it could explain the question :)
Thanks again.
You must create a new partial part of your entity class (in the new .cs file) and add new fields to that class. You must not modify the partial part created by autogeneration because autogenerated files will be overwritten every time you change EDMX file. You also must not include the field in EDMX because EDMX defines your mapping to database = it contains only fields in database.
Create a new file WebOrderPart.cs in the same assembly and namespace as your autogenerated classes containing:
public partial class Weborder
{
public string newField1 {get; set;}
public string newField2 {get; set;}
}
Dosn't [NotMapped] work.
[NotMapped]
public string newField1 {get; set;}
First of all, you shouldn't modify the data model file. This file represents your data.
Second, you shouldn't be returning your data model objects/collections from your Repository. This is a very bad practice because you are creating a dependency between the Controller/View and the Model. I suggest you create custom Model objects that contain the properties you need in your View, map your entities to those Model objects and only return Model objects or collections of Model objects from your Repository.

Wcf ria services - custom objects with EF entities - can't compile

I have custom entity (not from entity model), which have a property, wich return collection of EF entities (from entity model):
[DataContract]
public class MyEntity
{
[DataMember]
public List<Role> Roles { get; set; }
}
The 'Role' and 'RolePermission' entities are generated by EF4 from DB.
RolePermission has FOREGIN_KEY to Role, and EF4 was generated association between Role and RolePermission:
Role.RolePermissions --navigate property
RolePermission.Role --navigate property
Also, I have DomainService:
[EnableClientAccess()]
public class MyEntityService : DomainService
{
public List<MyEntity> GetMyEntities()
{
...
myEntityInstance.Roles = <GetRoles>
...
return <collection of MyEntities with Roles>
}
}
When I try to compile this, I get error:
Entity 'UserManager.Web.RolePermission' has a property 'RoleReference' with an unsupported type
When I put [Include] attribute to MyEntity.Roles property, I get the same error and this error:
Property 'Roles' of complex type 'MyEntity' is invalid. Complex types cannot have include members.
when I removed reference from RolePermission to Role (RolePermission.Role navigate property) by hands (from entity model), I get only this error in compile time:
The Entity 'Role' in DomainService 'RolesService' does not have a key defined. Entity types exposed by DomainService operations must have at least one public property marked with the KeyAttribute.
How can I resolve this situation? How can I return my custom object (MyEntity) with filled Roles property from MyEntityService?
A added [key] attr to Role.Metadata, and compile succesfull. But there are no MyEntity.Roles property on the client.
RIA services requires all objects passed back and forth between client to server to have a unique key so it knows which specific object you are modifying.
If you must have your own object as a wrapper for EF objects, just add an id member marked with [key] and maintain that value yourself.
[DataContract]
public class MyEntity
{
[key]
public int Id { get; set; }
[DataMember]
public List<Role> Roles { get; set; }
}
There seems to be something wrong with the design if you need to do that. What is the parent of a group of roles in your application? Why not just query roles?

Am I best off using a class or just the ID for an entity framework foreign key?

Basically put, I have an "Identity" table that has an ID and username, I have another table that has entries "owned" by a person, for that reason, I need to have a FK that links to the Identity table.
For example: Class "Identity" - int ID, string username.
I was just wondering which of the following is best:
Class "test" - int ID, string data, Identity identity
Class "test" - int ID, string data, int identity_id - with an annotation defining as foreign key.
I personally use the first, and seen that EF basically does the second behind the scene, but I was just wondering what the advantages/disadvantages are and what is best?
From the object oriented perspective the first is better because you have reference to the related object and it is what you expect when working with objects. In database this is performed by foreign key which defines relation between two records.
Entity framework offers both correct object oriented approach (the first one) and the approach where you include foreign key property in the entity as well. The reason is that exposing FK property will make some operations much more easier. Most common solution for the second approach is:
public class Test
{
public int Id { get; set; }
public string Data { get; set; }
[ForeignKey("Identity")]
public int IdentityId { get; set; }
public Identity Identity { get; set; }
}
You have both access to FK property and the entity. Those approaches have names: Independent association (the first one) and Foreign key association (the second one). There are more differences between them - I described them in another answer.

Resources