Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4840

What is best practice for tracking and attaching entities in Entity Framework and Blazor

$
0
0

I am new to Blazor and EF world but have reasonable experience with other frameworks such as django and laravel. I am trying to wrap my head around attaching the entities to a db context. It is said that IDbContextFactory is better than using DBContext due to its scope and I agree. However, I believe managing navigational properties and the amount of work that needs to be done to determine if entity is tracked or not seems to be counterproductive. Surely, I might be doing it wrong!Please do point if you identify anything I can improve

Current issue is that when I have two products or more setting EntityState.Unchanged the second time throws exception

System.InvalidOperationException: The instance of entity type 'ProductType' cannot be tracked because another instance with the key value '{Id: 2}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

Repository

public class JobRepository : IJobRepository    {        private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;        private readonly IUserService _userService;        public JobRepository(IDbContextFactory<ApplicationDbContext> contextFactory, IUserService userService)        {            _contextFactory = contextFactory;            _userService = userService;        } public async Task AddJobAsync(Job job)        {            if (job == null)            {                throw new ArgumentNullException(nameof(job));            }            try            {                using var _context = _contextFactory.CreateDbContext();                var user = await _userService.GetLoggedInUserAsync();                job.CreatedById = user.Id;                job.CustomerId = user.CustomerId.GetValueOrDefault();                if (job.Address != null)                {                    //_context.Attach(job.Address);                    _context.Entry(job.Address).State = EntityState.Unchanged;                }                if(job.Site != null)                {                    //_context.Attach(job.Site);                    _context.Entry(job.Site).State = EntityState.Unchanged;                }                if (job.CustomerId > 0)                {                    job.Customer = await _context.Customers.FindAsync(job.CustomerId);                    if (job.Customer != null)                    {                        //_context.Attach(job.Customer);                        _context.Entry(job.Customer).State = EntityState.Unchanged;                    }                }                if (job.Insurer != null)                {                    //_context.Attach(job.Insurer);                    _context.Entry(job.Insurer).State = EntityState.Unchanged;                }                foreach (var product in job.JobProducts)                {                    if (product.ProductId > 0 && product.Product!=null)                    {                        _context.Entry(product.Product).State = EntityState.Unchanged;                        if (product.Product.ProductType != null)                        {                            _context.Entry(product.Product.ProductType).State = EntityState.Unchanged;                        }                    }                }                job.CreatedAt = DateTime.Now;                _context.Jobs.Add(job);                await _context.SaveChangesAsync();            }            catch (Exception ex)            {                throw ex;            }        }}

Service that uses automapper

public async Task CreateJobRequestAsync(JobDTO job)        {            var jobEntity = _mapper.Map<Job>(job);            await _jobRepository.AddJobAsync(jobEntity);        }

JobDTO

namespace Shared.DTOs.Common.Jobs{    public class JobDTO    {        // Properties        public int Id { get; set; }        public DateTime CreatedAt { get; set; }        public DateTime? EarliestBy { get; set; }        public DateTime? LatestBy { get; set; }        public DeliveryPreference DeliveryPreference { get; set; }         public DeliveryTime DeliveryTime { get; set; }        public string? Instructions { get; set; }        public string? PurchaseOrderNumber { get; set; }        public string? CheckoutSessionId { get; set; }        // Relations        public int? AddressId { get; set; }        public AddressDTO? Address { get; set; }         public int? SiteID { get; set; }        public ProjectSiteDTO? Site { get; set; }        public string CreatedById { get; set; } = default!;        public ApplicationUserDTO CreatedBy { get; set; } = default!;                     public int CustomerId { get; set; }        public CustomerDTO? Customer { get; set; }         public int? InsurerId { get; set; }        public InsurerDTO? Insurer { get; set; }             public List<JobLifeCycleDTO> LifeCycleEntries { get; set; } = new List<JobLifeCycleDTO>();        public List<JobInviteDTO> Invites { get; set; } = new List<JobInviteDTO>();         public List<JobProductDTO> JobProducts { get; set; } = new List<JobProductDTO>();     }}

Model Job

namespace Shared.Entities.Common.Jobs{       public class Job    {        //Properties        public int Id { get; set; }        public DateTime CreatedAt { get; set; }        public DateTime? EarliestBy { get; set; }        public DateTime? LatestBy { get; set; }        public DeliveryPreference DeliveryPreference { get; set; }         public DeliveryTime DeliveryTime { get; set; }        public string? Instructions { get; set; }        public string? PurchaseOrderNumber { get; set; }        public string? CheckoutSessionId { get; set; }        //Relations        public int? AddressId { get; set; }        [ForeignKey("AddressId")]        public Address? Address { get; set; }        public int? SiteID { get; set; }        [ForeignKey("SiteID")]        public ProjectSite? Site { get; set; }        [Required]        public string CreatedById { get; set; }         [ForeignKey("CreatedById")]        public ApplicationUser CreatedBy { get; set; }        public int CustomerId { get; set; }        [ForeignKey("CustomerId")]        public Customer? Customer { get; set; }        public int? InsurerId { get; set; }        [ForeignKey("InsurerId")]        public Insurer? Insurer { get; set; }        public virtual ICollection<JobLifeCycle> LifeCycleEntries { get; set; } = new List<JobLifeCycle>();        public virtual List<JobInvite> Invites { get; set; } = new List<JobInvite>();        public virtual ICollection<JobProduct> JobProducts { get; set; } = new HashSet<JobProduct>();        //        public JobLifeCycle? LatestStatus => LifeCycleEntries.OrderByDescending(e => e.ActionedAt).FirstOrDefault();    }}

Viewing all articles
Browse latest Browse all 4840

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>