【问题标题】:Entity framework will replace a newly added record , with a record created inside the action method实体框架将用在 action 方法中创建的记录替换新添加的记录
【发布时间】:2015-04-22 18:13:08
【问题描述】:

我想实现这个简单的场景,虽然 EF 会开箱即用地支持它。 我有一个名为 (Skill) 的父记录,我正在向它添加名为 (LinktoKB) 的子记录。现在添加一个新的 LinktoKB 后,我想返回一个包含最新的 LinkToKB 列表的视图(包括新添加的)。 现在我添加新 LinktoKB 的 Post 操作方法是:-

[HttpPost]
[ValidateAntiForgeryToken]
[CheckUserPermissions(Action = "Edit", Model = "Skill")]
public async Task<ActionResult> AddKBLink(AssignKBLinksToSkill assignkblinkToSkill)
{          
    try
    {

        if (assignkblinkToSkill.LinkToKB == null)
        {
            return HttpNotFound();
        }
        if (ModelState.IsValid)
        {
            unitofwork.SkillRepository.AddKBLinkToSkill(assignkblinkToSkill, unitofwork.StaffRepository.GetLoginUserName(User.Identity.Name));
            await unitofwork.Save();

            //i have removed the values from the model state to prevent showing validation error "that the URL and name is required after succfully adding a new link"
            // also to show the modified values and not the binded values

            string   oldlinkURL = assignkblinkToSkill.LinkToKB.URL;

            ModelState.Clear();

            var skillAfterAddingKBLink = await unitofwork.SkillRepository.FindSkill(assignkblinkToSkill.Skillid, r => r.LinkToKBs);
            assignkblinkToSkill.LinktoKBList = skillAfterAddingKBLink.LinkToKBs.ToList(); //get the new lsit from DB after addign the new link
            assignkblinkToSkill.LinkToKB.URL = "http://";//reset the values , so that user will not get old vlues
            assignkblinkToSkill.LinkToKB.Name = String.Empty;

            if (Request.IsAjaxRequest())
            {
                TempData["Partialmessage"] = string.Format("{0} URL have been Added", oldlinkURL);


                return PartialView("AddKBLink", assignkblinkToSkill);
            }
            TempData["message"] = string.Format("{0} URL have been Added", oldlinkURL);

            return View("AddKBLink", assignkblinkToSkill);
        }
    }

我的存储库方法是:-

public async Task<Skill> FindSkill(int id, params Expression<Func<Skill, object>>[] includeProperties)    
{
    var query = context.Skills.AsQueryable();
    if (includeProperties != null || includeProperties.Count() != 0 || includeProperties[0].Name == "0")
        query = includeProperties.Aggregate(query, (current, include) => current.Include(include));
    return await query.SingleOrDefaultAsync(a => a.SkillID == id);
}

&

public void AddKBLinkToSkill(AssignKBLinksToSkill assignKBLinkToSkill,string username)
{
    var skill = context.Skills.SingleOrDefault(a=>a.SkillID == assignKBLinkToSkill.Skillid);
    skill.LinkToKBs.Add(assignKBLinkToSkill.LinkToKB);
    skill.Modified = System.DateTime.Now;

    skill.ModifiedBy = staffrepo.GetUserIdByUserName(username);

    context.Entry(skill).State = EntityState.Modified;
}

目前我得到一个非常奇怪的行为是,返回到视图的列表将不包含新添加的 LinkToKB 值,它将被以下值替换:-

assignkblinkToSkill.LinkToKB.URL = "http://"

尽管我明确地从数据库中检索 LinkToKB 列表,但是任何人都可以就此提出建议吗?

visual studio 将如何在以下两个不同阶段:-

首先这是新添加的LinkToKB:-

第二个 EF 已将其替换为操作方法中的值:-

我花了一整天的时间试图了解发生了什么......如果我删除了这些行:-

assignkblinkToSkill.LinkToKB.URL = "http://";//reset the values , so that user will not get old vlues
            assignkblinkToSkill.LinkToKB.Name = String.Empty;

我会正确获得新的最新列表(但我需要它们)..

我有两个模型类(Skill 和 LinktoKB):-

public partial class Skill
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Skill()
        {
            this.SkillLevels = new HashSet<SkillLevel>();
            this.SkillLevelStaffs = new HashSet<SkillLevelStaff>();
            this.Customers = new HashSet<Customer>();
            this.LinkToKBs = new HashSet<LinkToKB>();
            this.SkillVersionHistories = new HashSet<SkillVersionHistory>();
            this.Skill1 = new HashSet<Skill>();
            this.Skills = new HashSet<Skill>();
        }

        public int SkillID { get; set; }
        public string Name { get; set; }
       //code goes here 


        public virtual SkillStatu SkillStatu { get; set; }
        public virtual SkillType SkillType { get; set; }

        public virtual ICollection<LinkToKB> LinkToKBs { get; set; }

    }

{

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public LinkToKB()
    {
        this.Skills = new HashSet<Skill>();
    }

    public int LinkToKBID { get; set; }
    public string URL { get; set; }
    public string Name { get; set; }

   public virtual ICollection<Skill> Skills { get; set; }
}

以及下面的 viewModel 类:-

 public class AssignKBLinksToSkill
    {
     public ICollection<LinkToKB> LinktoKBList { set; get; }
     public LinkToKB LinkToKB { set; get; }
     public int Skillid { set; get; }

    }

【问题讨论】:

  • 这令人困惑。 LinktoKBListLinkToKBsLinkToKB之间是什么关系?
  • @GertArnold 抱歉,我从一开始就没有包括这个,我已经用 2 个模型类和视图模型更新了我的问题

标签: asp.net-mvc entity-framework asp.net-mvc-5 entity-framework-6 modelstate


【解决方案1】:

在您的代码中总是有一个assignkblinkToSkill.LinkToKB 实例。当它进入该方法时,它会获得一些您存储在数据库中的值。稍后您将其值重新分配为"http://"

但这仍然是您添加到列表中的实例skillAfterAddingKBLink.LinkToKBs

您只需在视图模型中创建一个新实例:

assignkblinkToSkill.LinkToKB = new LinkToKB();
assignkblinkToSkill.LinkToKB.URL = "http://";

【讨论】:

  • 但我仍然无法理解这种情况,因为在以下代码链接中“assignkblinkToSkill.LinktoKBList = SkillAfterAddingKBLink.LinkToKBs.ToList();”我正在从数据库中检索 LinkToKBs 列表,那么为什么 EF 修改了该列表?看起来这是一个错误?
  • 是的,没错,但 EF 永远不会通过查询覆盖本地值。该值已修改,因此 EF 保留此更改。毕竟,您可能想要保存它(您不知道,但 EF 不知道)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多