I'm writing a simple application that imports entities to CRM. Durring this import I need to associate imported entities (custom entity) to another (also custom) entities.
There's no problem with new objects, but when I try to update, I need to delete all associations regarding imported entity and recreated them based on imported data.
How can I do this?
I was thinking of getting all associated entities, and then call disassociate for each of them, but I got stuck trying to get those associated entities.
How should I approach this?
Suppose that you have Student Entity And you want to copy the student Cources to another custom Entity as you said named CStudent
You can use the following code:
var scs = Context.new_Student_CourcesSet.Where(x => x.new_courceid == Cource.Id).ToList<new_Student_Cources>();
var removedsc = Context.new_new_CStudent_CourcesSet.Where(x => x.new_cstudentid == CStudent.Id).ToList<new_CStudent_Cources>();
EntityReferenceCollection relatedEntities = new EntityReferenceCollection();
EntityReferenceCollection removedrelatedEntities = new EntityReferenceCollection();
Relationship relationship = new Relationship(new_CStudent_Cources.EntityLogicalName);
if (removedsc != null)
{
foreach (new_CStudent_Cources c in removedsc )
{
RemovedrelatedEntities.Add(new EntityReference(new_Cources.EntityLogicalName, (Guid)ar.new_courcesid));
}
Service.Disassociate(CStudent.LogicalName, CStudnetid, relationship, RemovedrelatedEntities);
}
foreach (new_Student_Cources d in scs)
{
relatedEntities.Add(new EntityReference(new_Cources.EntityLogicalName, (Guid)d.new_courceid));
}
Service.Associate(CStudent.LogicalName, CStudentid, relationship, relatedEntities);
Related
This question already has answers here:
Adding Item with Many-to-Many Relationship In Entity Framework
(2 answers)
Closed 7 years ago.
I seem to be stuck on a specific problem. I am using entity framework, and I have auto-generated all the entities from my database. I have noticed that any tables I have that serve as a bridging table to prevent a many-to-many relationship, don't actually have an entity; for example, the table I am trying to use called 'DiplomaCertificate' is linked to a table called 'Degree' through a bridging table called 'DegreeRelationship'. DegreeRelationship takes the primary key of both these tables, and uses them as its primary key, and foreign key. I noticed instead of an entity I get this in my context class:
modelBuilder.Entity<Degree>()
.HasMany(e => e.DiplomaCertificates)
.WithMany(e => e.Degrees)
.Map(m => m.ToTable("DegreeRelationship").MapLeftKey("DegreeID").MapRightKey("ProgramID"));
In my code behind, I have so far been handling processing inserts as follows:
public void InsertDiplomaProgram(DiplomaCertificate diplomaProgram, List<EntranceRequirementList> entReqList, List<int> degreeIDs)
{
using (Pathway_Model context = new Pathway_Model())
{
DiplomaCertificate added = null;
EntranceRequirement addedEntReq = null;
added = context.DiplomaCertificates.Add(diplomaProgram);
// create entrance requirement entry for each row entered
foreach (EntranceRequirementList entry in entReqList)
{
EntranceRequirement entReq = new EntranceRequirement()
{
ProgramID = added.ProgramID,
CourseID = entry.CourseID,
Marks = entry.Mark
};
addedEntReq = context.EntranceRequirements.Add(entReq);
}
//create degree diploma entry for each row entered
foreach (int entry in degreeIDs)
{
// normally I would try and use a foreach to populate new entries in the database,
// but right now I am not sure???
}
// commits the add to the databas
context.SaveChanges();
}
}
Basically I am trying to take the diplomaID, and go through and combine the list of degree ID's into the DegreeRelationship table, but I am stuck here. If anyone could offer a suggestion I would greatly appreciate it. Thank You!!
I am assuming below will work.
diplomaProgram.Degrees.Add(Degree)
It does make sense to use this structure as well. So DiplomaProgram will have its mapped Degree (vice versa) in its collection.
More Details
I am creating a MVC 2 website. I'm a beginner. I created a Model to use EF. The relationship is between a user table and a product table (one to many relationship). I am able to create new users and save them on the DB using linq to entities. My question is how do I add a product to an existing user. I was starting with the code below but it does not work. Intellisense doesn't see the queryuser.Product whats wrong with my code or what is the right way to do it. If someone can help me it would be great
public void Insert(Product obj)
{
if (HttpContext.Current.Session["userid"] != null)
{
string userid2 = HttpContext.Current.Session["userid"].ToString();
var queryuser = from p in entities.Users
where p.UserID == userid2
select p;
queryuser.Product.Add(obj);
entities.Users.Add(queryuser);
entities.SaveChanges();
}
}
I am calling this method from my controller.
queryuser is an IQueryable and you are treating it like a single object.
You might try replacing:
queryuser.Product.Add(obj);
entities.Users.Add(queryuser);
with
user = queryuser.First();
user.Product.Add(obj);
entities.Users.Add(user);
There is a many to many relationship between Artist and ArtistType. I can easily add artist ArtistType like below
foreach (var artistType in this._db.ArtistTypes
.Where(artistType => vm.SelectedIds.Contains(artistType.ArtistTypeID)))
{
artist.ArtistTypes.Add(artistType);
}
_db.ArtistDetails.Add(artist);
_db.SaveChanges();
This goes and updates the many to many association table with correct mapping. But when I try to remove any item from table I do not get any error but it does not remove it from the table?
foreach (var artistType in this._db.ArtistTypes
.Where(at => vm.SelectedIds.Contains(at.ArtistTypeID)))
{
artistDetail.ArtistTypes.Remove(artistType);
}
this._db.Entry(artistDetail).State = EntityState.Modified;
this._db.SaveChanges();
What am I missing?
Standard way is to load the artist including the current related types from the database and then remove the types with the selected Ids from the loaded types collection. Change tracking will recognize which types have been removed and write the correct DELETE statements to the join table:
var artist = this._db.Artists.Include(a => a.ArtistTypes)
.SingleOrDefault(a => a.ArtistID == someArtistID);
if (artist != null)
{
foreach (var artistType in artist.ArtistTypes
.Where(at => vm.SelectedIds.Contains(at.ArtistTypeID)).ToList())
{
artist.ArtistTypes.Remove(artistType);
}
this._db.SaveChanges();
}
For removing only one field, I came up with this solution. It seems odd but in EF, most of the things are odd anyway because we try to tell EF the database ops in terms of OOP.
using (var db = new Context())
{
//Create existing entities without fetch:
var artist = new Artist() { ArtistID = _artistID };
var type = new Type() { TypeID = _typeID };
//Add one entity to other's list
//This is in memory, not connected.
//So we do this because we try to tell EF that we want to remove this item
//Without fetch, we should add it first in order to remove :)
artist.ArtistTypes.Add(type);
//Attach that entity which you add an item to its list:
db.Artists.Attach(artist);
//It's now connected and recognized by EF as database operation
//After attaching, remove that item from list and save db
artist.ArtistTypes.Remove(type);
db.SaveChanges();
}
That's it! With this solution, you are no longer fetching all entries of joined table ArtistTypes.
How do I delete a record in a junction table within Entity Framework 5?
When reverse engineering my DataContext, Entity Framework seems to have recognized my junction table and automatically added Collections to my Models to represent the M:M relationship. This is great when adding items, as I can simply build my entire Entity and everything gets inserted properly. Perfect.
However, I'm stumped on removing a relationship. For example, an Activity can have multiple Contacts associated to it, and this is linked using a junction table (dbo.ActivityContacts) that consists of the columns:
ActivityID
ContactID
Both my Activity and Contact models have been updated by EF with Collections to represent the other. For example, my Activity model looks like this:
public class Activity
{
public int ActivityID { get; set; }
public string Subject { get; set; }
public virtual ICollection<Contacts> Contacts { get; set; }
}
In a non-EF environment, I would simply delete the record from the junction table and move on with my day. However, it seems I cannot access the junction table directly using EF, so I'm a tad confused on how to remove the record (relationship).
How can I properly remove a record from a junction table in Entity Framework?
Agree with #Chris.
Another solution is to do:
context.Entry(activity).State = EntityState.Deleted;
Entity Framework should remove the record for you, if you remove the associated object from either side of the relationship.
Assuming you've obtained this Activity instance from your context and want to remove a specific Contact with a known ID:
unwantedContact = context.Contacts.Find(contactID);
myActivity.Contacts.Remove(unwantedContact);
context.SaveChanges();
Should delete the record in your junction table, unless I'm being daft.
ali golshani did a good job providing a solution. Let me try to expand on it a little more. In my scenario I have two list boxes where you can move items left or right (selected or not selected)
The 'dto' object below is sent from the client. It's checking the selected state for each item in the list. If anyone knows of any way to improve this any more please leave feedback.
file_appender selectedAppender = context.file_appender.Find(dto.Id);
int[] ids = dto.Loggers.Where(x => !x.Selected).Select(x => x.Id).ToArray();
var loggers_to_delete = selectedAppender.logger.Where(x => ids.Contains(x.id));
loggers_to_delete.ToList().ForEach(x =>
{
selectedAppender.logger.Remove(x);
});
ids = dto.Loggers.Where(x => x.Selected).Select(x => x.Id).ToArray();
var loggers_to_add = context.logger.Where(x => ids.Contains(x.id));
loggers_to_add.ToList().ForEach(x =>
{
selectedAppender.logger.Add(x);
});
Lets look at another example....This one is for a list box with embedded check boxes (a little simpler). Honestly this could probably be applied to the solution above to make easier to read code.
protected void saveRelatedConnectors(test_engine testEngine, List<int> connectorTypes)
var stepConnectorsToDelete = testEngine.step_connector.Where(x => (connectorTypes.Count == 0) ||
(connectorTypes.Count != 0 && !connectorTypes.Contains(x.id)));
stepConnectorsToDelete.ToList().ForEach(x =>
{
testEngine.step_connector.Remove(x);
});
var stepConnectorsToAdd = entities.step_connector.Where(x => connectorTypes.Contains(x.id));
stepConnectorsToAdd.ToList().ForEach(x =>
{
testEngine.step_connector.Add(x);
});
entities.SaveChanges();
contact_to_delete = context.Contacts.Find(contactID);
selected_activity = context.Activity.Find(ActivityID);
context.Entry(selected_activity).Collection("Activity").Load();
selected_activity.Contacts.Remove(contact_to_delete);
db.SaveChanges();
I've a Entity Framework 4.0, with poco object. the edmx model file is generated from the database.
This datacontext is accessed through WCF service, it's only mean that I receive some objects and I need to attach them to the current datacontext(or reload them with the key correspondance).
Everything seems to work fine, except for one case:
I've a N-N relationship between two table, so I've an association table, without any field other than ID of two tables:
LINQ transform this into the following schema, this seems to be right.
When I retrieve data, there is no problem, data I've inserted myself in the Right_group are correctly transformed into "new object in my collection of Rights/Groups".
But if I try to modify something and save, it doesn't work
public void SaveRights(Group group, List<Rights> rights){
//here, group and rights are objects attached to the database
group.Rights.Clear();
group.Rights.AddRange(rights);
_dataContext.SaveChanges();
}
So my question is: How to save this "relationship" of two objects ?
Thank you!
If you want to avoid loading the objects from the database first you can do it like this(Code taken from one of my aplications so you will have to adapt it):
public void AddAndRemovePersons(int id, int[] toAdd, int[] toDelete)
{
var mailList = new MailList { ID = id, ContactInformations = new List<ContactInformation>() };
this.db.MailLists.Attach(mailList);
foreach (var item in toAdd)
{
var ci = new ContactInformation { ID = item };
this.db.ContactInformations.Attach(ci);
this.db.ObjectStateManager.ChangeRelationshipState(mailList, ci, ml => ml.ContactInformations, System.Data.EntityState.Added);
}
foreach (var item in toDelete)
{
var ci = new ContactInformation { ID = item };
this.db.ContactInformations.Attach(ci);
this.db.ObjectStateManager.ChangeRelationshipState(mailList, ci, ml => ml.ContactInformations, System.Data.EntityState.Deleted);
}
}
I found deleting the relationship as hard as creating it so I left that code in there. One thing about this solution is that both the maillist and the contacts exist prior to this function being run. I attach them to make the state manager track them.
If you are adding new objects that you also want to save you would use the
this.db.MailLists.AddObject(you new item here)
I hope that helps!
Just a thought... how are the keys setup in the Right_Group table? If you use both IDRight and IDGroup together as primary key - this problem might occur. One suggetion is to add a new column (ID) into the Right_Group table, and having this ID as the primary key. Then use foreign keys on the other columns (IDRight, IDGroup) respectivly.