Unable to execute insert statement while saving in symfony (propel) form with map list - forms

In doSave() function in form I'm trying to save article category (which it is a node in a tree), and then assign to this category articles (many to many relationship).
I'm getting an error while in $this->saveWaArticleNewsCategoryMapList($con); line. (Project is builded on symfony 1.4.16). There is no error when I assign article to an existing category.
public function doSave($con = null) {
$scope = $this->getValue('tree_scope');
$toEdit = $this->getObject();
if ($toEdit->isNew()) {
$node = new ArticleCategory();
$node->setBrandId($this->getValue('brand_id'));
$node->setName($this->getValue('name'));
$node->setTreeScope($scope);
$root = ArticleCategoryQuery::create()->findRoot($scope);
if ($root == null) {
$root = new ArticleCategory();
$root->setName('Root');
$root->setTreeScopeIdValue($scope);
$root->makeRoot();
$root->save($con);
$node->insertAsLastChildOf($root);
$node->save($con);
return;
}
$parent = ArticleCategoryQuery::create()->findPk($this->getValue('parent_id'));
$node->insertAsLastChildOf($parent);
} else {
$node = ArticleCategoryQuery::create()->findOneByArticleCategoryId($toEdit->getArticleCategoryId());
$node->setBrandId($this->getValue('brand_id'));
$node->setName($this->getValue('name'));
if ($toEdit->getParent()->getArticleCategoryId() != $this->getValue('parent_id')) {
$parent = ArticleCategoryQuery::create()->findPk($this->getValue('parent_id'));
$node->moveToLastChildOf($parent);
}
}
$node->save($con);
$this->saveArticleNewsCategoryMapList($con); <--Error
$this->saveArticleHelpCategoryMapList($con);
}
Error:
Unable to execute INSERT statement [INSERT INTO `article_news_category_map` (`ARTICLE_ID`) VALUES (:p0)] [wrapped: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`projectname`.`article_news_category_map`, CONSTRAINT `article_news_category_map_FK_2` FOREIGN KEY (`category_id`) REFERENCES `article_category` (`article_category_id`) ON DELETE CASCADE)]

Updating ArticleCategoryId in object solved the problem:
$node->save($con);
$this->getObject()->setArticleCategoryId($node->getArticleCategoryId());
...

Related

Entity Framework is failing to delete a record from an associated table throwing an error

I have a simple association table whose PK isn't referenced anywhere but when I am trying to delete a record from it in the following way, I get an error. I am using EF code-first. Any help would be very very helpful. Thanks in advance.
List<ViolationTypeNOV> novRels = UnitOfWork.Context.ViolationTypeNOVs.Where(x => x.NOVId == nov.NOVId).Include("ViolationType").Include("NOV").ToList();
foreach (ViolationTypeNOV o in novRels)
{
UnitOfWork.Context.ViolationTypeNOVs.Remove(o);
}
UnitOfWork.Context.SaveChanges();
Here is the error message I am getting. If the table's PK isn't referenced in any way, why is it failing with this error? Just not able to understand:
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.
The same thing if I am running through SSMS same thing is working though:
DELETE ViolationTypeNOVs
WHERE ViolationTypeNOVId = 2
Why?
But again if I am running the same query through context as below, I get the same error at the calling SaveChanges:
foreach (ViolationTypeNOV o in novRels)
{
string str = string.Format("Delete ViolationTypeNOVs where ViolationTypeNOVId = {0}", new object[] { o.ViolationTypeNOVId });
UnitOfWork.Context.Database.ExecuteSqlCommand(str);
}
UnitOfWork.Context.SaveChanges();
It seems like some of the objects within the context aren't nulling or getting deleted, is there anyway to clear them all in one go? Because these ids/objects are used in multiple places in the code - please let me know how to clear them all - thanks a lot.
Any help please?
Fixed it - the problem is we need to clear up all the objects and its links that the parent object is using then only we can save the changes thanks here is my solution
public bool Delete(NOV nov, bool performCommit = true)
{
System.Data.Entity.DbContextTransaction dbOperation = null;
if (performCommit)
dbOperation = UnitOfWork.BeginTransaction();
try
{
//-- Remove the Items - "foreach" approach was a problem
// http://weblogs.asp.net/ricardoperes/entity-framework-pitfalls-deleting-orphans
//------------------------------------------------------
// Remove the Violations that are in this NOV
//------------------------------------------------------
List<Violation> violationIdlist = new List<Violation>();
foreach (var v in nov.ViolationNOVs)
{
var a = UnitOfWork.ViolationRepository.GetAll().Where(z => z.ViolationId == v.ViolationId).FirstOrDefault();
violationIdlist.Add(a);
}
foreach (var v in violationIdlist)
{
var a = nov.ViolationNOVs.Where(x => x.NOVId == nov.NOVId && x.ViolationId == v.ViolationId)?.FirstOrDefault();
nov.ViolationNOVs.Remove(a);
}
nov.IssuedBy.Clear();
//deleting all OneToMany references to NOV
List<ViolationTypeNOV> novRels = UnitOfWork.Context.ViolationTypeNOVs.Where(x => x.NOVId == nov.NOVId).Include("ViolationType").Include("NOV").ToList();
nov?.ViolationTypeNOVs?.Clear();
//foreach (ViolationTypeNOV o in novRels)
//{
// UnitOfWork.Context.ViolationTypeNOVs.Remove(o);
// o?.ViolationType?.ViolationTypeNOVs?.Remove(o);
// nov?.ViolationTypeNOVs?.Remove(o);
//}
UnitOfWork.Context.ViolationTypeNOVs.RemoveRange(novRels);
List<ViolationNOV> violationNOVs = UnitOfWork.Context.ViolationNOVs.Where(x => x.NOVId == nov.NOVId).Include("Violation").Include("NOV").ToList();
nov?.ViolationNOVs?.Clear();
UnitOfWork.Context.ViolationNOVs.RemoveRange(violationNOVs);
List<CaseNOV> caseNOVs = UnitOfWork.Context.CaseNOVs.Where(x => x.NOVId == nov.NOVId).Include("Case").Include("NOV").ToList();
nov?.CaseNOVs?.Clear();
UnitOfWork.Context.CaseNOVs.RemoveRange(caseNOVs);
UnitOfWork.Context.SaveChanges();
if (dbOperation != null)
dbOperation.Commit();
LogHandler.LogInfo(2521, "Deleted NOV " + nov.NOVNumber);
return true;
}
catch (Exception ex)
{
LogHandler.LogError(2523, "Commit Fail in NOV Delete", ex);
if (dbOperation != null)
dbOperation.Rollback();
throw ex;
}
}
This statement has fixed the problem: UnitOfWork.Context.ViolationTypeNOVs.RemoveRange(novRels); thanks a lot for everybody who tried to help me

get primary key of last inserted record with JPA

I've been using JPA to insert entities into a database but I've run up against a problem where I need to do an insert and get the primary key of the record last inserted.
Using PostgreSQL I would use an INSERT RETURNING statement which would return the record id, but with an entity manager doing all this, the only way I know is to use SELECT CURRVAL.
So the problem becomes, I have several data sources sending data into a message driven bean (usually 10-100 messages at once from each source) via OpenMQ and inside this MDB I persists this to PostgreSQL via the entity manager. It's at this point I think there will be a "race condition like" effect of having so many inserts that I won't necessarily get the last record id using SELECT CURRVAL.
My MDB persists 3 entity beans via an entity manager like below.
Any help on how to better do this much appreciated.
public void onMessage(Message msg) {
Integer agPK = 0;
Integer scanPK = 0;
Integer lookPK = 0;
Iterator iter = null;
List<Ag> agKeys = null;
List<Scan> scanKeys = null;
try {
iag = (IAgBean) (new InitialContext()).lookup(
"java:comp/env/ejb/AgBean");
TextMessage tmsg = (TextMessage) msg;
// insert this into table only if doesn't exists
Ag ag = new Ag(msg.getStringProperty("name"));
agKeys = (List) (iag.getPKs(ag));
iter = agKeys.iterator();
if (iter.hasNext()) {
agPK = ((Ag) iter.next()).getId();
}
else {
// no PK found so not in dbase, insert new
iag.addAg(ag);
agKeys = (List) (iag.getPKs(ag));
iter = agKeys.iterator();
if (iter.hasNext()) {
agPK = ((Ag) iter.next()).getId();
}
}
// insert this into table always
iscan = (IScanBean) (new InitialContext()).lookup(
"java:comp/env/ejb/ScanBean");
Scan scan = new Scan();
scan.setName(msg.getStringProperty("name"));
scan.setCode(msg.getIntProperty("code"));
iscan.addScan(scan);
scanKeys = (List) iscan.getPKs(scan);
iter = scanKeys.iterator();
if (iter.hasNext()) {
scanPK = ((Scan) iter.next()).getId();
}
// insert into this table the two primary keys above
ilook = (ILookBean) (new InitialContext()).lookup(
"java:comp/env/ejb/LookBean");
Look look = new Look();
if (agPK.intValue() != 0 && scanPK.intValue() != 0) {
look.setAgId(agPK);
look.setScanId(scanPK);
ilook.addLook(look);
}
// ...
The JPA spec requires that after persist, the entity be populated with a valid ID if an ID generation strategy is being used. You don't have to do anything.

entity framework update

i know how to do updates, inserts and deletes with the entityframework but in this case i don't know what to do.
In this case i have 3 tables: the table A the table B and the table AB which has 2 columns, one is the foreing key of the table A and one is the foreing key of the table B.
The entity framework shows only the tables A and B so how i can update only the content of the table AB?
I've tried to use the references in entity A and entity B but it gives me an exception saying that the entityset AB doesn't have the insert function and the delete function.
You try to make a
Public Virtual List<int> Ids
in your "A" and "B" Class to recover all the associations
For an insert, you would create a record for Table A, then add the Table B records to the item created that inserts into A. EF will handle the rest.
var tableA = new TableAtype { Description = "blah", etc.};
tableA.TableBtype.Add(new TableBtype { Property1 = "foo", Property2 = "bar"};
yourContext.AddToTableAtype(tableA);
yourContext.SaveChanges();
i'll be more specific using the code of my project as asked by TheGeekYouNeed
public void ModificaAbilitazioni(int IdGruppoAnagrafica, List<DefAbilitazioni> AbilitazioniList)
{
GruppiAnag gruppo = (from g in entities.GruppiAnags
where g.IdGruppoAnag == IdGruppoAnagrafica
select g).First();
List<DefAbilitazioni> tutteAbilitazioni = GetTutteAbilitazioni();
for (int i = 0; i < AbilitazioniList.Count; i++)
{
if (tutteAbilitazioni[i].GruppiAnags.Contains(gruppo))
{
tutteAbilitazioni[i].GruppiAnags.Remove(gruppo);
}
}
foreach (DefAbilitazioni abilitazione in AbilitazioniList)
{
for (int i = 0; i < tutteAbilitazioni.Count; i++)
{
if (tutteAbilitazioni[i].IdAbilitazione == abilitazione.IdAbilitazione)
{
tutteAbilitazioni[i].GruppiAnags.Add(gruppo);
}
}
}
entities.SaveChanges();
}
ok...here it is
this method should change the privilegies accounts.
First i recover the account using his id, than i recover all the privilegies and if in their reference they have the account recovered, then i remove it from the reference.
This way the account doesn't have any privilegies. Now in the privilegies that i've passed calling the method and in theri reference i put the account. (just a wipe and refill i'm just trying for now...)
i've also di the opposite, wiping the privilegies references in the account and refill them, but in both way won't work, in the first case it says that the third entity (AB) doesn't have the insert function
i've resolved the thing, the problem was that i was working with objects not attached to the db, i've tried with the attach like this
foreach (DefAbilitazioni abilitazione in abilitazioni)
{
entities.Attach(abilitazione);
gruppo.DefAbilitazionis.Add(abilitazione);
}
but it doesn't work it says that the entitykey is null, maybe if somebody gives me an example of using the attach i'll try to change my code that now is like this
public void ModificaAbilitazioni(int IdGruppoAnagrafica, List<DefAbilitazioni> AbilitazioniList)
{
GruppiAnag gruppo = (from g in entities.GruppiAnags
where g.IdGruppoAnag == IdGruppoAnagrafica
select g).First();
IEnumerable<int> idAbilitazioni = from id in AbilitazioniList
select id.IdAbilitazione;
List<DefAbilitazioni> abilitazioni = (from abilitazione in entities.DefAbilitazionis
where idAbilitazioni.Contains(abilitazione.IdAbilitazione)
select abilitazione).ToList();
gruppo.DefAbilitazionis.Clear();
foreach (DefAbilitazioni abilitazione in abilitazioni)
{
gruppo.DefAbilitazionis.Add(abilitazione);
}
entities.SaveChanges();
}

Entity Framework the delete statement conflicted with the reference constraint

I have two tables Employee (n) and Store (1), which have n:1 relationship.
Employee has foreign key idStore which is primary key from Store.
Here is how I try to delete a row from Employee:
public void deleteEmployee(int idEmployee)
{
MyEntities pe = new MyEntities();
try
{
var firstQuery = from e in pe.Employees
where e.idEmployee == idEmployee
select e;
string findIdStore = firstQuery.First().StoreReference.EntityKey.EntityKeyValues[0].Value.ToString();
int idStore = Int32.Parse(findIdStore);
Store r = pe.Stores.First(c => c.idStore == idStore);
r.Employees.Remove(firstQuery.First());
pe.DeleteObject(firstQuery.First());
pe.SaveChanges();
}
catch (Exception ex)
{
return;
}
}
And still, I get error that the delete statement conflicted with the reference constraint.
The complete error is here:
The DELETE statement conflicted with the REFERENCE constraint
"FK_Bill_Employee". The conflict occurred in database
"myDatabase", table "dbo.Bill", column 'idEmployeeMember'.
The statement has been terminated.
Can't you just find and delete the employee??
public void deleteEmployee(int idEmployee)
{
using(MyEntities pe = new MyEntities())
{
var emmployeeToDelete = pe.Employees.FirstOrDefault(e => e.idEmployee == idEmployee);
if(employeeToDelete != null)
{
pe.DeleteObject(employeeToDelete);
pe.SaveChanges();
}
}
}
I don't think you need to do anything more than this, really.....
Next time when you load this particular store the employee belonged to, that employee will no longer be in the store's collection of employees - without doing any messy manual deletes or anything....

updating table in entity framework 4 /mvc 3!

could you help with this? I bet this isn't any tough one..but am new to EF and facing a weekend deadline. I want to update a table with values.. but the primary key is identity column. So my task is like this.. if it exists, update.. if it doesn't add to the
table.. this is my code..and am stuck in this else part..!
Table structure is like this
Primary Key table - System: SystemId, SystemName
Foreign Key table - SystemConfiguration: SystemConfigurationId, SystemId, SystemRAM, SystemHard-Disk
public void SaveSystemConfigurations(SystemConfiguration systemConfig)
{
var config = (from s in Context.SystemConfiguration
where s.SystemId == systemConfig.SystemId
select s).FirstOrDefault();
if (config == null)
{
Context.SystemConfigurations.AddObject(systemConfig);
Context.SaveChanges();
}
else
{
// EntityKey systemConfigKey= new EntityKey("systemConfig", "systemConfigId", config.SystemConfigurationId);
Context.SystemConfigurations.Attach(systemConfig);
Context.SaveChanges();
}
}
Try this:
public void SaveSystemConfigurations(SystemConfiguration systemConfig)
{
var config = (from s in Context.SystemConfiguration
where s.SystemId == systemConfig.SystemId
select s).FirstOrDefault();
if (config == null)
{
Context.SystemConfigurations.AddObject(systemConfig);
}
else
{
config.Attribute = value; // Do your update here
}
Context.SaveChanges();
}
Edit. It should be config not systemConfig.
The ApplyCurrentValues method will apply scalar attributes to an entity that matches the same key. My assumption is that you are modifying a real entity (an object that has a valid entity key).
This would work:
var eSet = config.EntityKey.EntitySetName;
Context.ApplyCurrentValues(eSet, systemConfig);
Context.SaveChanges();
public void SaveSystemConfigurations(SystemConfiguration systemConfig)
{
var context = new EntitiesModel();
//here is the name of the partial class created on the Context area of the edmx designer.cs
var config = (from s in context.SystemConfiguration
where s.SystemId == systemConfig.SystemId
select s).FirstOrDefault();
context.ApplyCurrentValues(config.EntityKey.EntitySetName, systemConfig);
// systemConfig comes from the view with values set by the user
// you dont have to manually need to map one value at the time
context.SaveChanges();
}