EF 4.1 and two-level object inserts fail - entity-framework-4

I am trying to create a complex structure in my database. My table structure is:
Parent
ID
Hier
ID
ParentHierID
Desc
Child
ID
ParentID
HierID
Sibling
ID
ChildID
SiblingTypeID
SiblingType
ID
Desc
Here's what I'm doing:
_objectSet = _context.CreateObjectSet<Parent>();
Parent p = Mapper.Map(ParentView, Parent>(parentView);
Child c;
Sibling s;
foreach ( var hier in TopLevels)
{
c = new Child();
c.HierId = hier.ID;
..set some other fields from foo...
p.Childs.Add(c);
s = new Sibling();
s.SiblingTypeID = 1;
c.Siblings.Add(s);
}
_objectSet.AddObject(p);
_context.SaveChanges(SaveOptions.None);
This results in an exception:
The INSERT statement conflicted with the FOREIGN KEY constraint
"Sibling_Child_FK". The conflict occurred in database "DB",
table "Child", column 'ID'.
The statement has been terminated.
If I don't create the Sibling, and remove c.Siblings.Add(s); then everything works. (Note that there is a trigger on the Child table that inserts the rest of the hierarchy from the Hier table).
Should EF4.1 be able to handle inserting multiple levels of objects like this? Am I missing something?

Just in case anyone else runs into this, the problem is because of the trigger.
Eliminating the trigger eliminated the problem, and I can create 3-4 levels deep and save it without any issues.

Related

Invalid table alias when joining multiple tables in hive

Can someone identify why this multi-table join is not accepted? When I bring in the third table, it then fails with invalid table alias. I am not seeing what is wrong:
This works (two table):
select
a.ri as `R_ID`
,oc3.name as `RET`
,a.rch as `RC`
from dev.sl a join dev.codes oc3
on (a.pk_business = oc3.pk_business
and a.pk_data_source = oc3.pk_data_source
and a.pk_frequency = oc3.pk_frequency
and oc3.pk_data_state = '123'
and oc3.code = a.ri and oc3.codeset = 'xyz')
Then add a third table and it fails:
(Three table):
select
a.ri as `R_ID`
,oc3.name as `RET`
,a.rch as `RC`
from dev.sl a join dev.codes oc3
on (a.pk_business = oc3.pk_business
and a.pk_data_source = oc3.pk_data_source
and a.pk_frequency = oc3.pk_frequency
and oc3.pk_data_state = '123'
and oc3.code = a.ri and oc3.codeset = 'xyz') join dev.items b
on (b.pk_business = a.pk_business
and b.pk_data_source = a.pk_data_source
and b.pk_frequency = a.pk_frequency
and b.pk_data_state = '123'
and a.ii = b.item_id
and a.cc = b.country_code)
SemanticException [Error 10009]: Line 1:2920 Invalid table alias 'a':
I have an update - it seems that this was caused by having one table created as an updatable table (TBLPROPERTIES ('transactional'='true')), and one without, and with my session settings of:
SET hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
SET hive.support.concurrency=true;
SET hive.enforce.bucketing=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
This caused the problem. On another session without the settings AND repointing to an identical table "a" created as a non-ACID type table, the multi-table join worked fine. I don't know enough about HIVE to know why - I suspect that a transactional and non-transactional table cannot be joined in the same "transaction" (select statement).
One more update - It may not be due to the transactional table. With additional testing, I now also see it happens with non-transactional tables as well. It seems that the three table join works when I execute it from a putty session directly on the server, but when I use SQL Developer, it will produce the aforementioned error. It appears to be an issue with SQL Developer, but why still is unknown.

autogenerated keys for entities with multipart keys

I was trying to create a new object with multicolumn primary key formed by a foreign key and a self-generated field and I found this error:
Ids can not be autogenerated for entities with multipart keys.
For now, and although not the most appropriate, I will change the key but the question is:
Are you planning support multicolumn primary key autogenerated soon?
I will add the request to uservoice too.
A greeting.
Edit to explain the use case:
Hello,
True, it may not make sense to have a primary key composed by a foreign key and a self-generated field.
My idea was to build a table like this:
ParentID ChildID Data
1 1 Some Data...
1 2 Some Data...
2 1 Some Data...
2 2 Some Data...
As a first step I did a table like this:
ParentID ChildID Data
1 1 Some Data...
1 2 Some Data...
2 3 Some Data...
2 4 Some Data...
Where ChildID was a self-generated field.
So you can ignore my question.
A greeting.
I've had the same problem but I have successfully solved it without changing the Primary Key (PK).
My PK had 2 columns
ProductId (identity)
TenantId (multitenant application)
so the first problem was Breeze couldn't generate new PK when the new item was added to the EntityManager. And I have defined custom entity initialization function:
var manager = new breeze.EntityManager(breezeServiceUrl);
var store = manager.metadataStore;
function itemInitializer(item) {
if (item.ProductId() == 0) {
item.ProductId(/*Some counter value*/);
}
if (item.TenantId() == 0) {
item.TenantId(TenantId);
}
if (item.isBeingEdited === undefined) {
item.isBeingEdited = ko.observable(false);
}
};
store.registerEntityTypeCtor("ProductItem", function() {/*Leave empty to use default constructor*/}, itemInitializer);
The second problem is that Breeze couldn't update the ProductId with the real value from EntityFramework because it gets the entity by PK and the returned value had only ProductId. So you need to override the function:
var entityType = store.getEntityType("ProductItem");
var entityGroup = manager.findEntityGroup(entityType);
entityGroup._fixupKey = function (tempValue, realValue) {
var ix = this._indexMap[tempValue + ":::" + TenantId]; //Changed line
if (ix === undefined) {
throw new Error("Internal Error in key fixup - unable to locate entity");
}
var entity = this._entities[ix];
var keyPropName = entity.entityType.keyProperties[0].name;
entity.setProperty(keyPropName, realValue);
delete entity.entityAspect.hasTempKey;
delete this._indexMap[tempValue];
this._indexMap[realValue] = ix;
};
If you have any other questions about multipart keys, you can read it in the blog.
This feature is not currently on the roadmap, but I want to better understand your use case for this. As you already know, Breeze supports auto-generated keys, and Breeze supports multi-part keys, but what scenarios do you find using both at the same time to be helpful?
Thanks!
Actually having a multipart key where part of the key is autogenerated is actually pretty common. This usually occurs with legacy databases where the primary key consists of a foreign key property and a 'autogenerated' sequence number property. Usually this autogenerated key is not globally unique by itself, but only in conjunction with the foreign key property. Think of an orderDetail with a foreign key of "OrderId, SequenceNumber".
What doesn't seem to make as much sense is when the primary key consists of more than one autogenerated property.
In Breeze the autogenerated keys are intended to be globally unique. Whereas, in the multipart key mentioned above the SequenceNumber would not be globally unique ( and if it were then why not make it the primary key all by itself).
Does this make sense?

Copy an object with relations in which there is a Sortable object throws an Duplicate Entry error

In an old projet using symfony 1.4 There are an object Product linked to other objects such as Translation ProductPlatform ...
What I want to do is copy the Product object with all its relations.
Pretty simple with $product->copy(true) BUT
It doesn't copy the relations, so i need to do :
$this->loadReference('Translation');
$this->loadReference('ProductPlatforms');
foreach ($this->ProductPlatforms as $platform) {
$platform->loadReference('Translation');
}
$newProduct = $this->copy(true);
$newProduct->save();
return $newProduct;
The throwed error is this :
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-131' for key 'product_platform_position_sortable_idx'
What I don't understand is the following requests :
SELECT p.id AS p__id, p.position AS p__position FROM product_platform p
WHERE (p.product_id = 'EndNote (copie)') ORDER BY p.position desc LIMIT 1;
----
INSERT INTO product_platform (publish_configuration, product_id, platform_id, position)
VALUES ('1', '131', '1', '1')
And then, it reinsert, for another object, the same position :
INSERT INTO product_platform (publish_configuration, product_id, platform_id, position)
VALUES ('1', '131', '3', '1');
Why there is, instead of an ID, the Name of my object in the Where clause WHERE (p.product_id = 'EndNote (copie)'). I think this is the reason it tries to insert the same value.
Ok, it's a bug with the Sortable behaviour, we sent a PR :
https://github.com/bshaffer/csDoctrineActAsSortablePlugin/pull/25

The member with identity ' ' does not exist in the metadata collection.\r\nParameter name: identity

I simplified the code a little while trying to debug:
[HttpPost]
public ActionResult Register(User model)
{
DateTime bla = new DateTime(2012, 12, 12);
try
{
User user = new User
{
gid = 1,
cid = 1,
firstName = model.firstName,
lastName = model.lastName,
email = model.email,
username = model.username,
password = model.password,
creationDate = bla,
active = 1
};
myContext.Users.AddObject(user);
myContext.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
return View();
}
The values are transmited accordingly. Users table:
[id] [int] IDENTITY(1,1) NOT NULL,
[cid] [int] NULL,
[gid] [int] NULL,
[firstName] [nvarchar](100) NOT NULL,
[lastName] [nvarchar](100) NOT NULL,
[email] [nvarchar](max) NOT NULL,
[username] [nvarchar](100) NOT NULL,
[password] [nvarchar](100) NOT NULL,
[creationDate] [datetime] NOT NULL,
[active] [int] NOT NULL,
CONSTRAINT [PK_Users_3213E83F0AD2A005] PRIMARY KEY CLUSTERED
I deleted all the foreign keys to be sure that nothing affects it. I am qute certain that at a previous moment it was working, but now I can not figure where the issue is.
It crashes while performing the savechanges:
{"An error occurred while updating the entries. See the inner exception for details."}
{"The member with identity '' does not exist in the metadata collection.\r\nParameter name: identity"}
I had the same error being thrown when I try to insert using EF, the error was
The member with identity 'Id' does not exist in the metadata collection.\r\nParameter name: identity
It wasn't obvious at first but the exception message was very concise because my database knows the column Id int but the property created for the object on my code was int ID so coming back to named mapping, Id is not mapped to ID.
So when an object with property ID is sent to database that only know Id you will get the above error.
I hope this helps, thanks
The issue was reproducing because of a trigger that was on the users table. Removed it and the issue is not reproducing anymore.
There is probably a trigger on the table being updated and it returns output. The output is thrown away but it conflicts with EF. Such output is often used to debug triggers (and forgotten to delete later):
select 'trigger called, i am here'
or there can be missing variable:
select column
instead of
select #variable=column
I think that the best solution is in this post. I used the 3rd option and works.
Here I report the reply in the link:
The issue could be related to a "instead of insert" trigger on one of
your tables.
The EF framework is performing validation on the inserted row of data
by calling scope_identity(). However, an "instead of insert" trigger
will change the context of the insertion in such a way that the EF
system's call to scope_identity will return null.
A couple ways around this:
Use a stored procedure to insert the data ( not tested )
Remove the instead of insert trigger ( triggers can cause other problems, so some people argue not to use them) ( tested, works!)
Turn off validation in the EF framework, so: context.Configuration.ValidateOnSaveEnabled = false ( tested, works!)
I had this same error today and spent a few frustrating hours trying to figure it out.
I was using Entity Framework to insert a record with an identity column into a SQL server database table. Simple enough.
The table had a trigger on it which in turn ran a stored procedure. The stored procedure had a line in it:
select newid()
This is the line that broke Entity Framework.
For tables with identity columns, Entity Framework expects to be returned a single row with a single field that is the identity column.
it's because of trigger pass back value to EF
if you are using trigger. in my problem i must check a value by selecting from other table and using of 'select' cause error in EF, so you must replace 'select' with 'set'.
you can not use this code.
select #any= any from tablename
you should use set instead of select
set #any= (select any from tablename)
Somedays, I hate M$.
The member with identity 'ChangeID' does not exist in the metadata collection.
Parameter name: identity
I've spent two days trying to get around this.
I'm using MVC.
To get all the data I need in one fell swoop, I created a view of the table in the DB for this application, and tables in other databases. (You may update views, with some constraints.)
I do a get, and all my data is present in the record, keys, descriptions, foreign keys, etc.
I created triggers on my view, to update the portion of the view that came from the local table.
Instead of Delete worked fine.
Instead of Update worked fine.
This error kept raising it's head on Instead of Insert. I could NOT get the insert trigger to successfully insert into my table. If I ran an insert on the view, with all fields provided in the SQL Management Studio, it worked fine. I know the exact values being passed because I ran SQL Server Profiler to see the code being passed.
But when the app attempted the update, it failed with The member with identity 'ChangeID' does not exist in the metadata collection.
Clue up above, someone said, "MVC expects table key to be ID"
I renamed ChangeID as ID in my view, changed it in the App, and BAM! Now it works.
What did NOT work:
db.Configuration.ValidateOnSaveEnabled = false;
adding a select to the trigger to get scope identity
Why do I have to modify my DB or my view to satisfy some hidden M$ assumption?
None the less, after two very frustrating days, code is now working. Maybe this will save someone else some time as well.
Try this
[HttpPost]
public ActionResult Register(User model)
{
DateTime bla = new DateTime(2012, 12, 12);
try
{
model.gid = 1;
model.cid = 1;
model.creationDate = bla;
model.active = 1;
myContext.Users.AddObject(model);
myContext.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
return View();
}
I was having this issue and my fix, was that in my connection-string metadata I did not specify my model in the .msl format.
See more info here
In my case, SetName of the entity was incorrect. Shortly, this worked for me:
Use
myContext.AddObject(nameOfSetEntity, user);
Instead of:
myContext.Users.AddObject(user);
To get the whole correct name of the entity (thanks to Nix's answer)
string className = typeof(User).Name;
var container = myContext.MetadataWorkspace.GetEntityContainer(myContext.DefaultContainerName, System.Data.Metadata.Edm.DataSpace.CSpace);
string nameOfSetEntity= (from meta in container.BaseEntitySets
where meta.ElementType.Name == className
select meta.Name).First();
Context.AddObject(nameOfSetEntity, user);

Entity Framework 4 Linq help - Pulling data from multiple tables filtered

Not sure how this is done, I have my .edmx set up so that the navigation properties match the foreign key relationships on the tables. Not sure if I still need to perform joins or if EF will give me access to the related table data through the navigational properties automatically.
What I need to do it get all the ContentSections and their associated ContentItems based on the ContentView and filtered by the DiversionProgram.CrimeNumber.
I would like to get back IEnumerable, for each ContentSection it should have access to it's ContentItems via the navigation property ContentItems
Thanks
Something like:
using(Entities context = new Entities())
{
IEnumerable<ContentSection> enumerator = context.ContentSections
.Include("ContentItems")
.Where<ContentSection>(cs => cs.ContentView.ContentViewID == someID && cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber))
.AsEnumerable<ContentSection>
}
I've interpreted
based on the ContentView
as cs.ContentView.ContentViewID == someID
This will give you all the ContentSections for a given ContentView. And interpreted
filtered by the DiversionProgram.CrimeNumber
as cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber)
which will give you all those ContentItems that have a specific CrimeNumber.
Or did you mean something else with based on / filtered by. Maybe OrderBy, or all those ContentSections where Any of it's ContentItems would have a certain CrimeNumber?
You can eager load to get all associated records, but when you want to start filtering/ordering, don't bother with Include.
Just do a projection with anonymous types and EF will work out what it needs to do. It's a bit hairy, but it'll work. If it get's too complicated, bite the bullet and use a SPROC.
Now, with that caveat, something like this (off the top of my head):
var query = ctx.ContentView
.Select(x => new
{
ContentSections = x.ContentSections
.Where(y => y.ContentItems
.Any(z => z.DivisionProgram.CrimeNumber = 87))
}).ToList().Select(x => x.ContentSections);
If you use the CTP5 you can do something very unique it looks like this:
var context = new YourEntitiesContext();
var query = context.ContentView.Include(cs => cs.ContentSections
.Select(ci => ci.ContentItems
.Select(dp => dp.DiversionProgram)
.Where(dp.CrimeNumber == crimeNumber)))
.Where(cv => cv.ContentViewID == contentViewID).FirtsOrDefault();
You can learn more about the CTP5 and how it can be used in Database first scenario here
var query = from t1 in studentManagementEntities.StudentRegistrations
join t2 in studentManagementEntities.StudentMarks
on t1.StudentID equals t2.StudentID
select new
{
t1.selected column name,
t2.selected column name
};

Resources