为什么我的实体被多个 IEntityChangeTracker 实例引用?

我正在尝试通过将我的 DbContext 注入服务类来在我的 ASP.NET Web 窗体项目中实现现代实践(使用服务、IoC 等),但我一直收到一条错误消息An entity object cannot be referenced by multiple instances of IEntityChangeTracker.


这让我很困惑,因为我相对确定我只有一个 DbContext 跟踪更改。


有什么问题?我正在使用将 DbContext 作为函数参数发送到的静态类,但除此之外,我没有在页面端进行任何更改...


public partial class Create : System.Web.UI.Page

{

    private LicenseService licenseService;


    private ApplicationDbContext context = new ApplicationDbContext();

    protected void Page_Load(object sender, EventArgs e)

    {

        try

        {

            licenseService = new LicenseService(context);

        }

        catch (Exception ex)

        {

            // TODO Add error handling/logging.

            ErrorMessage.Text = ex.Message;

        }

    }

    protected void Page_LoadComplete(object sender, EventArgs e)

    {

        this.context.Dispose();

    }


    protected async void Save_Click(object sender, EventArgs e)

    {

        try

        {

            var userManager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();

            var user = await userManager.FindByIdAsync(User.Identity.GetUserId());


            await SaveLicenseAsync(user);


            // Show a message that the work was done.

            ShowSnackbar("License was successfully added; redirecting...", "Default");

        }

        catch (Exception ex)

        {

            // TODO Add error handling/logging.

            ErrorMessage.Text = ex.Message;

        }

    }


    private async Task SaveLicenseAsync(ApplicationUser user)

    {

        // Get the specified expiry date.

        DateTime.TryParse(ExpiryDatePicker.SelectedDate.ToString(), out DateTime expiryDate);


        // Create the viewmodel that will be passed to the service.

        var model = new LicenseViewModel

        {

            ExpiryDate = expiryDate,

            Name = NameTextBox.Text

        };

        await licenseService.AddAsync(model, user);

    }

}

我的服务通常包含与 EF 的所有交互。我喜欢这个,因为它将页面与 DbContext 逻辑分开。


HUH函数
浏览 93回答 1
1回答

潇潇雨雨

问题将与您在许可证中的用户参考有关。这是从 Owin 上下文中检索到的,但您正在尝试将其保存/关联到您的许可证上下文。我将更新该方法以简单地接受用户 ID,然后从您的许可证上下文加载并关联用户。public async Task AddRangeAsync(IEnumerable<LicenseViewModel> models, int ownerId){&nbsp; &nbsp; var list = new List<License>();&nbsp; &nbsp; var owner = context.Users.Single(x => x.UserId == ownerId);&nbsp; &nbsp; foreach (var model in models)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; list.Add(new License&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ExpiryDate = model.ExpiryDate,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name = model.Name,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; User = owner&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; &nbsp; context.Licenses.AddRange(list);&nbsp; &nbsp; await context.SaveChangesAsync();}那应该可以解决您的问题。偷偷摸摸的小细节。:)为了避免负载,您可以使用:var owner = context.Owners.Local.SingleOrDefault(x => x.UserId == ownerId);if (owner == null){&nbsp; &nbsp; owner = new User{UserId = ownerId};&nbsp; &nbsp; context.Users.Attach(owner);}// ...我可能会考虑将其放在基类方法中以从上下文中检索所有者引用。该方法的警告是,除非您从数据库显式加载,否则此上下文中的用户将不包含有关用户的详细信息。(即名称等)因此,只要团队知道不相信上下文将具有完整的用户,除非明确重新加载,就可以从性能 PoV 中获得。
打开App,查看更多内容
随时随地看视频慕课网APP