I am trying to delete the child objects in foreach loop but that doesn't seem to be working.. Here is what I have.
I have a meeting and meeting_category entities which has 1-to-many relationship..
foreach (meeting_category meetingCategory in currentMeeting.meeting_category)
{
dbContext.meeting_category.Remove(meetingCategory);
dbContext.Entry(meetingCategory).State = EntityState.Deleted;
dbContext.SaveChanges();
}
I am then returning to the same view with updated results.. This seems to be very inconsistent. Sometimes it deletes entities and sometimes it doesn't. Even when it deletes it, my meeting object still have meeting_category objects I deleted.
When it doesn't delete from DB, it updates the meeting object and removed meeting_category objects from the meeting..
Is there any kind of reset or refresh that I will have to do in order for meeting object to remove the meeting_category objects..
How can I make sure that it consistently deletes the meeting_category objects both from DB and from the meeting object and when I return to the view, I have an updated meeting object?
Here is my meeting entity
public partial class meeting
{
public meeting()
{
this.meeting_questions = new HashSet<meeting_questions>();
this.meeting_abstract = new HashSet<meeting_abstract>();
this.meeting_category = new HashSet<meeting_category>();
this.meeting_image = new HashSet<meeting_image>();
}
public int meeting_id { get; set; }
public int language_id { get; set; }
public string meeting_code { get; set; }
public string meeting_name { get; set; }
public string meeting_description { get; set; }
public System.DateTime meeting_start_date { get; set; }
public System.DateTime meeting_end_date { get; set; }
public System.DateTime abstract_cutoff_date { get; set; }
public string meeting_guidelines { get; set; }
public string created_by { get; set; }
public Nullable<System.DateTime> created_datetime { get; set; }
public Nullable<bool> meeting_published { get; set; }
public Nullable<bool> meeting_deleted { get; set; }
public Nullable<bool> meeting_fully_created { get; set; }
public virtual language language { get; set; }
public virtual ICollection<meeting_questions> meeting_questions { get; set; }
public virtual ICollection<meeting_abstract> meeting_abstract { get; set; }
public virtual ICollection<meeting_category> meeting_category { get; set; }
public virtual ICollection<meeting_image> meeting_image { get; set; }
}
And here is my meeting_category entity
public partial class meeting_category
{
public meeting_category()
{
this.abstract_category = new HashSet<abstract_category>();
}
public int meeting_category_id { get; set; }
public int meeting_id { get; set; }
public int category_type_id { get; set; }
public int category_id { get; set; }
public string category_name { get; set; }
public string category_name_en { get; set; }
public virtual ICollection<abstract_category> abstract_category { get; set; }
public virtual category category { get; set; }
public virtual category_type category_type { get; set; }
public virtual meeting meeting { get; set; }
}
I have a couple of questions about what it is that you are trying to achieve.
Firstly are you sure that the Meeting -> Category relationship is many-to-one? I would normally expect it to be many-to-many, i.e. each Meeting can have many Categories and each Category can be attached to many Meetings.
Secondly, are you actually trying to delete the Category or are you trying to remove a Category from a Meeting?
If you are simply trying to remove the relationship between a Meeting and a Category then you need to edit the navigation property, i.e. MyMeeting.Categories.Remove(MyCategory).
If you are trying to delete the actual Category then you will need to make sure that that Category is not currently linked to any Meeting otherwise you will get a Foreign Key violation if you try to remove the Category.
On top of all of this you may be encountering chaching or simply object lifetime management issues.
What type of application are you creating? ASP.NET? WinForms? etc.
How are you actually instantiating a concrete version of your DBContext? Are you using DI?
Cheers Mike
I managed to fix the issue by creating the DbContext per controller action and destroying it before loading the view.
The problem was that I was creating the DbContext in another class and was reusing the same context on all controller action. Since Entities are cached in dbcontext, I was always getting the old cached copy of entities and was working very inconsistently.
Related
I need to update a child list from a parent adding records to it or updating one of its attributes. I receive the updated model from the Controller but when I try to replace the actual list with the new and save the changes to DB I get the error:
The instance of entity type 'WorkflowReferenciaExecucoes' cannot be tracked because another instance with the same key value for {'ReferenciaExecucoesId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
I don't have access to the dbContext directly because we are using the repository pattern. What I have tried to update the child in the service is:
private void Update(Workflow entity)
{
// entity is my updated model received by controller
// Getting the actual parent in the database
var workflow = GetById(entity.WorkflowId);
workflow.NomeWorkflow = entity.NomeWorkflow;
workflow.DescricaoWorkflow = entity.DescricaoWorkflow;
workflow.FgAtivo = entity.FgAtivo;
// Updating child list
workflow.WorkflowReferenciaExecucoes = entity.WorkflowReferenciaExecucoes;
// Trying to save the update gives error
_uow.WorkflowRepository.Update(entity);
}
My parent class is:
public class Workflow
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int WorkflowId { get; set; }
public int ProjetoId { get; set; }
public int WorkflowTipoId { get; set; }
public string NomeWorkflow { get; set; }
public string DescricaoWorkflow { get; set; }
public DateTime DataInclusao { get; set; }
public bool FgAtivo { get; set; }
public Projeto Projeto { get; set; }
public WorkflowTipo WorkflowTipo { get; set; }
public IEnumerable<WorkflowReferenciaExecucao> WorkflowReferenciaExecucoes { get; set; }
public IEnumerable<WorkflowCondicaoExecucao> WorkflowCondicaoExecucoes { get; set; }
}
And child class:
public class WorkflowReferenciaExecucao
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ReferenciaExecucaoId { get; set; }
public int WorkflowId { get; set; }
public int? ExecucaoWorkflowId { get; set; }
public int ValorReferenciaExecucao { get; set; }
public bool FgProcessar { get; set; }
public bool FgAtivo { get; set; }
}
What do I have to do to update the actual list to the new one?
Thank you!
Could it be that the passed in entity has duplicates in the WorkflowReferenciaExecucoes property - meaning the same WorkflowReferenciaExecucao exists twice in that IEnumerable?
you can not update like that you have wrong relationship you class should be like that
public class WorkflowReferenciaExecucao
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ReferenciaExecucaoId { get; set; }
public Workflow Workflow { get; set; }
public int? ExecucaoWorkflowId { get; set; }
public int ValorReferenciaExecucao { get; set; }
public bool FgProcessar { get; set; }
public bool Fugitive { get; set; }
}
WorkflowReferenciaExecucao is one and it has only one workflow so when you update Workflow then you have to update only workflow id in WorkflowReferenciaExecucao don't pass whole object just pass id to change it one to many relationship so on one side you update anything it don't relate to many relationship because it only point to id that it
I can reproduce your problem when there are multiple child records with the same ReferenciaExecucoesId in the update entity.
You can check if this is the case.
I am having issues trying to map two fields that are foreign keys into the same table. The use case is for a modifier and creator. My class already has the Ids, and then I wanted to add the full User object as virtual.
I am using a base class so that each of my tables have the same audit fields:
public class Entity
{
public long? ModifiedById { get; set; }
public long CreatedById { get; set; } = 1;
[ForeignKey("CreatedById")]
public virtual User CreatedByUser { get; set; }
[ForeignKey("ModifiedById")]
public virtual User ModifiedByUser { get; set; }
}
The child class is very simple:
public class CircleUserSubscription : Entity
{
[Required]
public long Id { get; set; }
public long SponsorUserId { get; set; }
[ForeignKey("SponsorUserId")]
public virtual User User { get; set; }
public long TestId { get; set; }
[ForeignKey("TestId")]
public virtual User Test { get; set; }
}
This is a standard junction table.
When I try to generate the migration, I am getting errors that I don't understand fully.
Unable to determine the relationship represented by navigation property 'CircleUserSubscription.User' of type 'User'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
I tried what this answer had, but the code is basically the same: https://entityframeworkcore.com/knowledge-base/54418186/ef-core-2-2---two-foreign-keys-to-same-table
An inverse property doesn't make sense since every table will have a reference to the user table.
For reference, here is the User entity:
public class User : Entity
{
public long Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
I am hoping you all can help me out, TIA :)
EDIT: One thing to note, all of this worked fine when the entity class was as follows:
public class Entity
{
public long? ModifiedById { get; set; }
public long CreatedById { get; set; } = 1;
}
It was only after I added the entity that things went awry.
I'm new to c# and I have a basic problem with saving/updating data.
With two classes :
public class User
{
public int UserId { get; set; }
public string Email { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public DateTime RegisteredDate { get; set; }
public class Task
{
public int TaskId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Comment { get; set; }
public User DeclaredBy { get; set; }
}
I'm trying to save a task object (new or updated) with DeclaredBy field set
dbContext.Tasks.AddOrUpdate(task);
dbContext.SaveChanges();
User set in DeclaredBy field has an ID, but after executing SaveChanges() a new record of User appears in DB.
This is how EF works, if you add entity with other related entity then both will be stored in DB. If you want to store only one then you need to set other navigation properties to null and only set foreign key id, which currently you don't have, you should add property:
public int DeclatedById { get; set; }
Btw. this is very common problem and a lot of projects has duplicate values in db.
Maybe I should add that this will happen only if entity wasn't traced by EF context and was attached to it.
Using Entity Framework Code first I have a class that holds data for a drop-down list. The same class holds records that are sub-items for the items in the main list. Ultimately this will create a cascading set of drop-down lists.
I am trying to figure out how to make the navigation property for the class link back to itself. The issue class is the one that I am using to populate the drop-down list. The Complaint class also has a link to the Issues class but does not need a link back to the subcategory.
public class Issue
{
public Issue()
{
Complaints = new List<Complaint>();
SubIssues = new List<Issue>();
}
[Key]
public int IssueID { get; set; }
public string Name { get; set; }
public bool IsSubCategory { get; set; }
[ForeignKey("IssueID")]
public ICollection<Issue> SubIssues { get; set; }
public virtual ICollection<Complaint> Complaints { get; set; }
}
public class Complaint
{
public Complaint()
{
}
public int ComplaintID { get; set; }
public string Name {get; set;}
[ForeignKey("IssueID")]
public virtual Issue Issue { get; set; }
}
I did something similar, but actually did only have a parent reference in the children. Either way this should work.
public class Folder
{
[Key]
public int Id { get; set; }
// Some Property
public string Name { get; set; }
// They foreignkey for Many-side
public virtual Folder Parent { get; set; }
// The list for One-side (Not tested in my application)
public virtual ICollection<Folder> SubFolders { get; set; }
}
It is same as a regular one-to-many relation, just all the references are within same entity.
Hi I'm learning to use MVc using Code first method. I'm having trouble understanding the use of ICollection<> with my setup. I have two classes/entitys: 'Restaurant' & 'RestaurantReview' as below:
public class Restaurant
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
public ICollection<RestaurantReview> Reviews { get; set; }
}
and.....
public class RestaurantReview
{
public int Id { get; set; }
public int Rating { get; set; }
public string Body { get; set; }
public string ReviewerName { get; set; }
public int RestaurantId { get; set; }
}
now whats confusing me is the last property of the Restaurant class. Why is it of type 'ICollection' and uses my RestaurantReview class as a parameter, what does it do, hope I
have made myself clear
It's a definition of one to many relationship.
With that property (sometimes called Navigation Property) Entity Framework will be able to connect Review with Restaurant it was written about. It will also allow you to get Review entities for given Restaurant entity really easily.
You can also remove public int RestaurantId { get; set; } from RestaurantReview class - That column is gonna be generated automatically by EF because of ICollection<RestaurantReview> in Restaurant class.