I am having a problem with updating a many to many table that does not exist in the edmx diagram.
QuestionGroups
PK - QuesitonGroupID
Questions
PK - QuestionID
This table does not exist in edmx : I am not able to update this table
QuestionGroupQuestions
PK - QuestionGroupID
PK - QuestionID
Answers
PK - AnswerID
This table I am able to update this table correctly
QuestionAnswers
PK - QuestionID
PK - AnswerID
Here the code
public ActionResult Create(int questionGroupID, QuestionVM questionVM)
{
Mapper.CreateMap<Question, QuestionVM>();
Question question = Mapper.DynamicMap<Question>(questionVM);
if (question.Answers != null)
{
question.Answers = new List<Answer>();
foreach (var answer in questionVM.Answers)
{
var questionAnswerToAdd = db.Answers.Find(answer.AnswerID);
question.Answers.Add(questionAnswerToAdd);
}
}
db.Questions.Add(question);
db.SaveChanges();
var questionGroup = db.QuestionGroups.Find(questionGroupID);
questionGroup.Questions.Add(question);
db.QuestionGroups.Add(questionGroup);
The above code is working. I do not want to update the QuestionGroup table. I just want to update the QuestionGroupQuestions table.
db.Entry(questionGroup).State = EntityState.Unchanged;
db.SaveChanges();
return RedirectToAction("Index", "Question");
}
Before the update there are already 2 existing records
QuestionGroupID, QuestionID
14,1
14,3
When adding a new question I get this error message
{"Violation of PRIMARY KEY constraint 'PK_QuestionGroupQuestions'. Cannot insert duplicate key in object 'dbo.QuestionGroupQuestions'. The duplicate key value is (14, 1).\r\nThe statement has been terminated."}
when mapping tables with many-to-many relation(QuestionGroups and Questions), the table which holds related ID's (QuestionGroupQuestions) does not maps to any entity, instead of it the other tow table is mapped to entities with many-to-many association, the association is a collection of instances from each other inside them, and when save any valid changes of these tow tables the EF automatically updates the third table (QuestionGroupQuestions) so it's not need to update QuestionGroupQuestions.
var questionGroup = db.QuestionGroups.Find(questionGroupID);
questionGroup.Questions.Add(question);
//The problem is here that you are adding questionGroup again. comment it and check
//db.QuestionGroups.Add(questionGroup); this cause a error, questionGroup already exists
now if you save the changes to db the QuestionGroupQuestions tables also should get updated.
Related
I have a table User { UserId, Name, Age } and License { LicenseId, Name, IsActive }. Also I have a table UserLicense { UserId, LicenseId } which connects both of these and has the record for all the users who hold a license. A user can hold multiple license and those appear as different rows in the UserLicense table.
Now I need to remove a particular license from the license table. I do not want to delete it outright, so I mark IsActive = false. However I do want to delete rows from the UserLicense table for that license Id.
I am using Entity Framework.
If it is a direct table, I would have done something like :
var lic = db.Licenses.Where(l => l.Id== licenseId).FirstorDefault();
db.Licenses.Remove(lic);
db.SaveChanges();
However since UserLicense is a table of foreign keys, Entity Framework does not allow me to access it directly using
public void DeleteLicensedUsers(Guid LicenseId)
{
db.UserLicenses.Where()
}
because the model does not contain an independent table for UserLicense as it is only a table of foreign keys.
So how do I delete all rows of UserLicense table for a particular licenseId using Linq and EF6?
If your entity class (I guess User), has navigation properties of type ICollection<Licence> by removing Licence from this collection you are actually removing items from UserLicense table. This is how Entity Framework handles many-to-many relationships in databases.
I faced a similar issue and you can solve it this way. I almost tend to avoid tables with just foreign keys and instead add another column to fix this issue.
var license = db.Licenses.Where(l => l.ID == LicenseId).FirstOrDefault();
var users = license.Users.ToList();
if (users != null)
{
foreach (var user in users)
{
license.Users.Remove(user);
}
}
I'm a little confused by your question. So if you mark a license as isActive = false, and still want to see that license appear on user's page, then there should still a record in UserLicense table associating the two.
That said, I believe this answer from a similar question will help you.
so essentially:
//include licenses in the user entity
var result = ctx.User.Include(x=>x.Licenses).Where(t=>t.Id == _id).FirstOrDefault()
//get the licenses you are looking for, either equal or use .Contains
var licensesOfUser = result.Where(x=>x.Licenses.Where(l=>l.id == _licenseId);
//remove them from entity and save.
result.Licenses.RemoveRange(licenseOfUser);
ctx.SaveChanges();
[edit: if you have license]
//include users in license entities
var result = ctx.License.Include(x=>x.Users).Where(t=>t.Id == _id).FirstOrDefault()
//get the users you are looking for, either equal or use .Contains
var usersOfLicenses = result.Where(x=>x.Users.Where(l=>l.id == _userId);
//remove them from entity and save.
result.Users.RemoveRange(licenseOfUser);
ctx.SaveChanges();
I have two tables with foreign key relationship (1 to many). How can I do that when I'll remove item from first table, it will delete automatically all values with it's foreign key from second table?
So when I'll remove item from 1 table it will remove all items from 2 table whih NameId = ID of 1 table
Depends on the database management system; with MS SQL Server, you can set a foreign key to "ON DELETE CASCADE" which does exactly what you're asking for.
http://www.techonthenet.com/sql_server/foreign_keys/foreign_delete.php
You could just write a function for that:
public void RemoveWithRelatedEntries(int table1ItemID)
{
using(var db = new dbEntities())
{
// get all entities of table 2
var tab2Entities = db.table2.Where(tab2Ent=>tab2Ent.table1Reference == table1ItemID);
// remove all those entities
foreach(table2Item item in tab2Entities)
{
db.table2.Remove(item);
}
// finally remove entity from table 1
var table1entitiy = db.table1.Find(table1ItemID);
db.table1.Remove(table1entity);
db.Save();
}
}
there are probably more elegant solutions but this was what came first to my mind.
I have a database of three tables:
FaceT PhotoT FacePhotoT
------ ------ ----------
FaceID PhotoID FaceID
Name Name PhotoID
Some additional columns
Actually, its two one to many relationships because of additional columns in link table. Anyway, inserting completely new records is working fine, but the question is, how I suppose to do record insert if I just want to insert new face to existing photo record? I get fresh new face name and existing photo name in which that face exists and what to do? I cannot create another photo record, because there are such file with same name uploaded to server (Name column in Photo table is unique), I have to check somehow if photo doesn't exist in the database and if it does, create records only in two other tables (FaceT and FacePhotoT), but I don't know how.
Assuming the following entity and mapping for PhotoT:
public class PhotoT
{
//your entity's other properties here
public virtual IList<FaceT> Faces { get; set; }
public PhotoT()
{
Faces = new List<FaceT>();
}
}
public class PhotoTMap : ClassMap<PhotoT>
{
public PhotoTMap()
{
//mapping for other properties here
HasManyToMany(x => x.Faces)
.Cascade.SaveUpdate() //or another Cascade option of your choice
.Inverse() //or Inverse on FaceT
.Table("FacePhotoT")
.ParentKeyColumn("PhotoID")
.ChildKeyColumn("FaceID");
}
}
You could just add a new FaceT to the collection of an existing PhotoT record like this:
PhotoT photo = session.Get<PhotoT>(1);
FaceT face = new FaceT();
photo.Faces.Add(face);
session.Update(photo);
tx.Commit();
I have a Profile(as shown in below image) Table Which whenever I try to remove a row from it, I face this error which indicates there is still data in foreign key in Tempprice table which is related to the Id in Lots table .
the problem is when its Lots table turn to Delete , there is still rows in Tempprice which have different Userid but same lotsid that have Ownerid or Winnerid which I want to Delete.
And I don't know how to delete this rows!? or which query is needed?
Database Relationships and Tables:
Code:
while (checkbox.Checked)
{
// Retreive the ID
int ida = Convert.ToInt32(GridView1.DataKeys[row.RowIndex].Value);
// Pass the value of the selected Id(s) to the Delete //command.
//These numbers indicate in which order tables shoulde be deleted
/*1*/
new BLL.LoginBLL().Delete(ida);
/*2*/
new BLL.MessageBLL().Delete(ida);
/*3*/
new BLL.JointBLL().Delete(ida);
/*4*/
new BLL.TemppriceBLL().Delete(ida);
/*5*/
new BLL.LotsBLL().Delete(ida);
/*6*/
new BLL.AuctionBLL().Delete(ida);
/*7*/
new BLL.ProfileBLL().DeleteProfile(ida);
checkbox.Checked = false;
}
ShowUsers();
To delete references, you need to set the relation (by selecting the line connecting the two objects) to Cascade for the End 1 On Delete property.
Then you need to Load the referenced object or collection. Calling Delete in this case, will delete your object and all objects it references.
I have two tables Team_DATA and Driver_PROFILE_DATA in an SQL database. For every driver_profile there can be many teams.
So there's a one-to-many relation on the driver_profile to team_data table. I want to update a team_data foreign key reference in the Driver_profile table of an already existing record to another team_data record that already exists.
I want to do this using entity framework. Here what I want: having a list of teams to select from, finding the record in the team_data table and updating it's FK in the driver_profile appropriately.
So in the code below, the passed parameter is the newly selected team out of the team_data table.
Now I need it to update it FK reference in the Driver_profile table.
Here's what I've got:
UPDATE: Code Updated. It does not save it to database, even if I call savechanges. No errors.
public Driver_PROFILE_DATA GetSelectedTeam(string team)
{
ObjectQuery<Team_DATA> td = raceCtxt.Team_DATA;
ObjectQuery<Driver_PROFILE_DATA> drpr = raceCtxt.Driver_PROFILE_DATA;
var selteam = from t in td where t.Team_Name == team select t;
Team_DATA newteam = new Team_DATA();
newteam = selteam.Select(x => x).First();
// get driver_profile with associated team_data
var data = from a in raceCtxt.Driver_PROFILE_DATA.Include("Team_DATA") select a;
// put it in driver_profile entity
profileData = data.Select(x => x).First();
profileData.Team_DATAReference.Attach(newteam);
return profileData;
}
Entity Framework should give you a nice Association between the two classes, Update the references as you would using POCOs and stay away from the ID values.
Something like:
newTeam.Profile.Teams.Remove(profileData); // separate from old Profile
profileData.Teams.Add(newTeam);
EDIT:
I made a little test, it is sufficient to set the reference to the Parent object:
newTeam.Profile = profileData;