Concurrency check fails with hierarchical data EF 4.0 - asp.net-mvc

I got a problem with Entity Framework 4.0
I have a hierarchical table Category: Id, Name, ParentCategory_Id, timestamp
The "timestamp" field is marked as "Concurrency Mode" = "Fixed"
And I'm using Self-Tracking Entity "Category" to manage Category entity in my MVC application.
The situation:
I create STE "NewCategory",
set field Name='bla-bla'
create new STE "ParentCategory" like this:
var ParentCategory = new Category{Id=45};
ParentCategory.MarkAsUnchanged();
NewCategory.Parent = ParentCategory;
Call ApplyChanges() method in my STE Context and call SaveChanges()
The Query is "Update Category set Name=...." !!!!!!
If I do NewCategory.Parent = null OR set "Concurrncy Mode" = "Node" in model scheme everything works FINE.
How to use hierarchical data with concurrency check ?

I solved this problem.
The solution is that the EF4.0 could manage theese situations only if you will use FK Assotiation properties.
In this sample the right way to do:
1)Create self assotiation in Category entity in edmx model. In "Referential Constraint" create link with parent entity via ParentCategory_Id property.
2) Create new instance of Category STE.
3) Set relation:
NewCategory.ParentCategory_Id = 45;
4) ApplyChanges, SaveChanges.

Related

Add column to database without defining it in model with Entity Framework

Is it possible to add a column (or execute some SQL) to a table when Entity Framework is instantiating a new database, without defining it in the Model used in DbSet ?
Iam building a prototype for a SaaS application with Entity Framework and Elastic Scale Client, and want to use Row Level Security, for that a need a column to identify my tenants. So i figured it would be nice if I could use just the EF initializer to add this column, when adding new tenants to the system.
As noted in the documentation here, you can execute sql when you have the DBContext.
From the docs:
using (var context = new BloggingContext())
{
context.Database.ExecuteSqlCommand(
"UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");
}
You could use this to modify the structure without having the actual structure defined in EF.

Does NHibernate have in-memory entities for updates

I am new to NHibernate. We are using Dapper for retrieval and planning to use NHibernate for CRUD.
I am trying to remove the child object through parent list object in one to many relationship.
This works when I retrieve the object using NHibernate session and remove the item.
var mercedes = Read("chevrolet"); //queries from nhibernate session
var model = mercedes.Models.Where(c => c.Id == 181).Single();
mercedes.Models.Remove(model);
When I manually create the object and attach thecars models, it is unable to remove it.
var mercedes = new Make() { Id = 77, Name = "chevrolet" };//manually created the object
mercedes.Models = GetAllModels(77);//I have it in-memory
var model = mercedes.Models.Where(c => c.Id == 173).Single();
mercedes.Models.Remove(model);
I think I am doing something weird. But I am able to add/update the models using second approach, so why can't i remove it. Any insights please.
When you create a new domain object it isn't attached to the NHibernate session (unless you are creating a new object and call Save, for instance). As such, deleting from the models collection doesn't actually do anything.
Your second example doesn't seem like a particularly good practice but you can recreate an object and attach it to your NHibernate session using Session.Lock (Merge or Update are fairly normal depending on your preferred behavior).

How to bypass the System.Data.Entity.Internal.InternalPropertyEntry.ValidateNotDetachedAndInModel(String method) validation of Entity framework?

I'm using a customized method for tracking individual modified properties of an n-tier disconnected entity class. I extracted it from
Programming Entity Framework: DbContext by Julia Lerman and Rowan
Miller (O’Reilly). Copyright 2012 Julia Lerman and Rowan Miller,
978-1-449-31296-1.
The code is:
public void ApplyChanges<TEntity>(TEntity root) where TEntity : class, IObjectWithState {
// bind the entity back into the context
dbContext.Set<TEntity>().Add(root);
// throw exception if entity does not implement IObjectWithState
CheckForEntitiesWithoutStateInterface(dbContext);
foreach (var entry in dbContext.ChangeTracker.Entries<IObjectWithState>()) {
IObjectWithState stateInfo = entry.Entity;
if (stateInfo.State == RecordState.Modified) {
// revert the Modified state of the entity
entry.State = EntityState.Unchanged;
foreach (var property in stateInfo.ModifiedProperties) {
// mark only the desired fields as modified
entry.Property(property).IsModified = true;
}
} else {
entry.State = ConvertState(stateInfo.State);
}
}
dbContext.SaveChanges();
}
The purpose of this method is to let the EF know only a predefined set of entity fields are ready for update in the next call of SaveChanges(). This is needed in order to workaround the entity works in ASP.NET MVC 3 as follows:
on initial page load: the Get action of the controller is loading the
entity object and passing it as a parameter to the view.
The View generate controls for editing 2 of the fields of the entity,
and holds the ID of the record in a hidden field.
When hitting [save] and posting the entity back to the controller all
of the fields excepting the 3 preserved in the view comes with a null
value. This is the default behavior of the MVC binding manager.
If i save the changes back to the database the update query will of course overwrite the non mapped fields with a sentence as follows:
UPDATE non_mapped_field_1 = NULL, ..., mapped_field_1 = 'mapped_value_1', mapped_field_2 = 'mapped_value_2', ... non_mapped_field_n = NULL WHERE ID = mapped_field_3
This is the reason i'm trying to track the fields individually and update only those fields i'm interested in. before calling the custom method with ApplyChanges() i'm adding the list of fields i want to be included in the update to the IObjectWithState.ModifiedProperties list, in order to get a SQL statement as follows:
UPDATE mapped_field_1 = 'mapped_value_1', mapped_field_2 = 'mapped_value_2' WHERE id = mapped_value_3
The problem is, when marking one of the fields as modified in ApplyChanges, i.e.:
entry.Property(property).IsModified = true;
the system is throwing the following exception:
{System.InvalidOperationException: Member 'IsModified' cannot be called for property 'NotifyCEDeadline' on entity of type 'User' because the property is not part of the Entity Data Model.
at System.Data.Entity.Internal.InternalPropertyEntry.ValidateNotDetachedAndInModel(String method)
at System.Data.Entity.Internal.InternalPropertyEntry.set_IsModified(Boolean value)
at System.Data.Entity.Infrastructure.DbPropertyEntry.set_IsModified(Boolean value)
...
So the question is. There's a way to bypass this EF validation or let the context know of the existance of this system property (IsModified) that i'm trying to change?
Summary of the architeture:
EF Code first (annotation + Fluent API)
Oracle .NET EF Data provider (ODAC)
Context is injected to a cutom business context with nInject.MVC => this is the reason i customized the ApplyChanges() method from
using (var context = new BreakAwayContext()){
context.Set().Add(root);
to a simple call to the already initialized dbcontext
dbContext.Set().Add(root);
Oracle Database is created manually i.e. without the help of EF, so no EF metadata tables are used.
Thanks,
Ivan.
Very good description, however I can't find any information on why you need a transient property called "IsModified" in the object and/or why you need to tell EF about it being modified (EF won't be able to persist it anyway).
The value of the IsModified property should be set by the model binder if the property was incldued in the view anyway.
You could just add code in your ApplyChanges method to skip a property named "IsModified", or even better, filter only known properties using entry.CurrentValues.PropertyNames, e.g.:
foreach (var property in stateInfo.ModifiedProperties) {
// mark only the desired fields as modified
if (entry.CurrentValues.PropertyNames.Contains(property)) {
entry.Property(property).IsModified = true;
}
}
Update: Ivan, very sorry I did not understand the problem better when you posted it several months ago and that I did not follow up after your added these clarifying comments. I think I understand better now. That said, I think the code snippet that I offered can be part of the solution. From looking at the exception you are getting again, I understand now that the problem that EF is detecting is that NotifyCEDDealine is not a persistent property (i.e. it is not mapped in the Code First model to a column in the database). IsModified can only be used against mapped properties, therefore you have two options: you change the code of the implementation of IObjectWithState in your entities so that non-mapped properties are not recorded in ModifiedProperties, or you use my code snippet to prevent calling IsModified with those.
By the way, an alternative to doing all this is to use the Controller.TryUpdateModel API to set only the modified properties in your entities.
Hope this helps (although I understand it is very late).

EF 4.0 adding relationship

HI
I have a project with uses EF self tracking objects.I am trying to add a relationship to an object . (parentobject.relationshipObject.Add(New relationshipObject...)).
But it throws an error:
Cannot change ObservableCollection
during a CollectionChanged or
PropertyChanged event.
This error occurs in the #Region "Association Fixup" of the code created by the template.
Initially the mainobject does not bring any relationship. Only when the item is selected by the user the relationships are updated in the item.
i found that if i remove the MainObject from the collection and readd it with the relationships this error does not occur. if i only update the relationship object in the mainObject , this issue occurs when i add a new relationship object from the client side
any help is much appreciated
--code sequence is as follows
1. get all the parent entities.
2. when user select an entity get the relationship of the entity and update the relationship entity
parentCol.AsEnumerable.Where(Function(x) x.ID = e.Result.ID).FirstOrDefault().StopTracking()
parentCol.AsEnumerable.Where(Function(x) x.ID = e.Result.ID).FirstOrDefault().relationshipEntity = e.Result.relationshipEntity
parentCol.AsEnumerable.Where(Function(x) x.ID = e.Result.ID).FirstOrDefault().StartTracking()
to add a new item in the relationEntity
Dim newRel As New relationshipEntity
newRel.Ref_parent_Id = parentItem.ID
newRel.REF_rel_ID = relItem.Id
parentItem.relationshipEntity.Add(newRel) ---> Throws error here
the relationshipEntity denotes the relationship table between the parent entity and another entity (many to many relationship).
thanks
Are you trying to add a new child while setting the child's parent?
Since EF tries to fix up one way links on two way relationships, I assume this could cause such an issue.
E.g.
parent.Add(new Child { Parent = parent, Name = "abc" });
As opposed to letting EF do the other side of the connection
parent.Add(new Child { Name = "abc" });
or
new Child { Parent = parent, Name = "abc" });

LINQ Modelling Automagically Retrieving Data Via EntityRef

I'm using LINQ to model my database, but I'm writing it by hand (Steve Sanderson recommends this in his ASP.NET MVC book). What I need to know is what's happening when you create an EntityRef, and how it's referenced. If I create my queries manually (without using LINQ), but use LINQ to model it, and I bring back just the ID of something, then reference the actual table column using EntityRef in the view, does it do the join, or does it re-query the database for that bit of information?
To clear things up, if I have this in my repository:
public IEnumerable<MyTable> ListMyTable(int? myColumnVar)
{
string query = "SELECT * FROM MyTable WHERE MyColumn = {0}";
return this.ExecuteQuery<MyTable>(query, myColumnVar);
}
and then in my controller I do this:
IEnumerable<MyTable> mytables = _contractsControlService.ListMyTable(1);
return View(mytables);
then in my view I do things like
<%=tbl.Ref.MyColumn %>
I'm referencing something set out by the LINQ model, but isn't actually in the table output. How does it get that data?
To clear things up further, we're using systems which require ultimate speed, so the LINQ-to-SQL is too slow for us, hence why we're using direct queries in our repository. I wouldn't mind using this EntityRef business if only I knew what was happening underneath.
You have most likely used the Object Relational designer to create an entity class for the Ref entity and an association between the MyTable and the Ref entity. You can also do that manually by creating the appropriate entity classes and using attributes to map the classes to the database schema. You can read the details in How to: Customize Entity Classes by Using the Code Editor (LINQ to SQL) on MSDN.
In your generated (or handwritten) code you will find some attributes:
[Table(Name="dbo.Ref")]
public partial class Ref : INotifyPropertyChanging, INotifyPropertyChanged
and
public partial class MyTable: INotifyPropertyChanging, INotifyPropertyChanged
{
[Association(Name="Ref_MyTable", Storage="_Ref", ThisKey="RefId",
OtherKey="Id", IsForeignKey=true)]
public Ref Ref
{
get
...
The entity classes combined with the attributes enables the Linq-to-Sql framework to retrieve entity classes directly from the database.
If you want to monitor the SQL genereated by Linq-to-Sql you can assign the DataContext.Log property:
context.Log = Console.Out;
In your example, navigating from MyTable to Ref, probably generates SQL along these lines:
SELECT Id, Field1, Field2, Field3
FROM Ref
WHERE Id = #RefId

Resources