На объектный объект нельзя ссылаться несколькими экземплярами IEntityChangeTracker, когда я пытаюсь создать сообщение - PullRequest
1 голос
/ 02 апреля 2020

Я пытаюсь создать сообщение, я не совсем уверен, почему я получаю эту ошибку. На объектный объект нельзя ссылаться несколькими экземплярами IEntityChangeTracker, если кто-то может пролить свет на меня

Это код в моем контроллере

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(NewPostModel model)
{
    var userId = User.Identity.GetUserId();
    var user = await UserManager.FindByIdAsync(userId);

    var post = BuildPost(model, user);
    await PostService.Instance.Add(post);

    return RedirectToAction("Index", "Post", new { id = post.Id });
}

private Post BuildPost(NewPostModel post, ApplicationUser user)
{
    var now = DateTime.Now;
    var forum = ForumServices.Instance.GetById(post.ForumId);

    return new Post
    {
        Title = post.Title,
        Content = post.Content,
        Created = now,
        Forum = forum,
        User = user,
        IsArchived = false
    };
}

А вот мой код в PostService

public async Task Add(Post post)
{
    using (var context = new ApplicationDbContext())
    {
        context.Posts.Add(post);
        await context.SaveChangesAsync();
    }
}

Когда я отлаживаю, контроллер получает модель и пользователя, однако, когда он достигает await PostService.Instance.Add(post);, он переходит к PostService, затем возвращается к строке ожидания в контроллере, затем я получаю ошибка. Я не уверен, что делать ...

Ответы [ 2 ]

0 голосов
/ 09 апреля 2020

Большое спасибо, я сделал так, как предложил, добавив ForumId и UserId к моделям

return new Post
{
     Title = post.Title,
     Content = post.Content,
     Created = now,
     ForumId = post.ForumId,
     UserId = user.Id,
     IsArchived = false
};
0 голосов
/ 02 апреля 2020

Вы получаете это исключение, потому что значения свойств forum и user принадлежат другому контексту Entity Framework.

При создании нового Post вы назначаете свойство Forum экземпляру форума. Этот экземпляр взят из ForumServices.Instance.GetById и связан с контекстом. Затем вы добавляете объект Post в другой контекст, экземпляр forum теперь связан с 2 контекстами, что невозможно.

Чтобы исправить это, вы можете изменить архитектуру, чтобы использовать один контекст EF для каждого запроса. Похоже, что вы используете одноэлементное (ForumServices.Instance), если используете ядро. net, вы должны взглянуть на то, как работает внедрение зависимостей, и использовать метод AddScoped, чтобы иметь единственный контекст EF на все время жизни запрос. Это решение, которое я настоятельно рекомендую.

Если невозможно изменить способ создания контекста, вы можете назначить Id вместо полного объекта

return new Post
{
    Title = post.Title,
    Content = post.Content,
    Created = now,
    ForumId = forum.ForumId,
    UserId = user.UserId,
    IsArchived = false
};

Если это по-прежнему невозможно, вы может вернуть неотслеживаемые объекты. Это можно сделать с помощью метода AsNoTracking или с помощью свойства QueryTrackingBehavior контекста

context.Forums.AsNoTracking().First(f => f.ForumId == forumId); 
// or
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...