Home > Software engineering >  How to get navigation properties with [Owned] attribute Tracked in Entity Framework Core
How to get navigation properties with [Owned] attribute Tracked in Entity Framework Core

Time:05-14

I got EF tracking turned off by default on my project.

I got a DB model class UserModel:

public class UserModel : BaseAdminDbModel
    {
        [Key]
        public int UserId { get; set; }

        [NotMapped]
        public string UserName { get; set; }

        [Required]
        public RightsModel R { get; set; }

        public BranchUserModel()
        {
            R = new RightsModel();
        }

        [ForeignKey("UserId")]
        public UserDataModel User { get; set; }
    }

RightsModel:

[Owned]
public class RightsModel
    {
        public bool? RightOne { get; set; }
        public bool? RightTwo { get; set; }
        public bool? RightN { get; set; }
    }

I want to add Owned navigation properties to be tracked before saving db context so every change in RightModel in UserModel will be saved to database (currently its ignoring those fields)

I want to have somewhat like this:

_dbContext.Entry(model).State = EntityState.Modified;

foreach(var navigationRightProperty in _dbContext.Entry(model).Navigations)
{
    navigationRightProperty.Load();
}

Result:

Changes to RightModel will be also tracked with the main UserModel entity.

CodePudding user response:

Model tracking is enabled by default for EF Core. So if you use the Include method on R property while making your request and making changes to it, then you call the SaveChanges method all changes will be saved in the database

var id = 1;
var model = _dbContext.UserModel.Include(x => x.R ).FirstOrDefalt(x => x.Id == id)

model.R.RightOne = true;

_dbContext.SaveChanges();

Also you can change your constructor for UserModel like

public UserModel()
{
    this.R = new HashSet<RightsModel>();
}

CodePudding user response:

After some time I came up to solve this issue. Drakk L solution is good if you have tracking turned on by default and want to rely on real objects.

I wanted more abstract way to achieve this:

var navigationOwnedProps = _dbContext
                .Entry(model)
                .Navigations
                .Where(e => e.Metadata
                    .ClrType.CustomAttributes.Any(c => c.AttributeType == 
                    typeof(OwnedAttribute))).Select(e => e.CurrentValue)
                .ToList();

foreach (var nav in navigationOwnedProps)
{
   _dbContext.Entry(nav).State = EntityState.Modified;
}
  • Related