Пользователь приложения идентификации ASP.NET MVC 5 как внешний ключ

Я знаю, что Visual Studio 2013 официально запускается завтра, и, надеюсь, будет больше сопроводительной документации, особенно в отношении ASP.NET Identity. Я надеюсь, что тем временем кто-то может мне помочь.

Все, что я пытаюсь сделать, это получить идентификатор пользователя вошедшего в систему пользователя в качестве внешнего ключа для таблицы, которую я назвал Retailer.

Сначала вот сообщение об ошибке, которое я получаю

На объект сущности не могут ссылаться несколько экземпляров IEntityChangeTracker.

Вот мой POCO:

public class Retailer
{
    [Key]
    public int RetailerId { get; set; }
    public string BusinessName { get; set; }
    public string PhoneNumber { get; set; }
    public string ManagerName { get; set; }
    public Enums.Industry Industry { get; set; }
    public virtual ApplicationUser UserProfile { get; set; }

}

Вот как Entity Framework CodeFirst создал таблицу из приведенного выше класса:

CreateTable(
    "dbo.Retailers",
    c => new
        {
            RetailerId = c.Int(nullable: false, identity: true),
            BusinessName = c.String(),
            PhoneNumber = c.String(),
            ManagerName = c.String(),
            Industry = c.Int(nullable: false),
            UserProfile_Id = c.String(maxLength: 128),
        })
    .PrimaryKey(t => t.RetailerId)
    .ForeignKey("dbo.AspNetUsers", t => t.UserProfile_Id)
    .Index(t => t.UserProfile_Id);

И вот где я пытаюсь сохранить запись в эту таблицу в своем контроллере:

if (ModelState.IsValid)
{
    var currentUser = await UserManager.FindByIdAsync(User.Identity.GetUserId());
    retailer.UserProfile = currentUser;
    db.Retailers.Add(retailer);
    await db.SaveChangesAsync();
    return RedirectToAction("Index");
}

И для полного раскрытия вот часть трассировки стека:

InvalidOperationException: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.]
   System.Data.Entity.Core.Objects.ObjectContext.VerifyContextForAddOrAttach(IEntityWrapper wrappedEntity) +189
   System.Data.Entity.Core.Objects.ObjectContext.AddSingleObject(EntitySet entitySet, IEntityWrapper wrappedEntity, String argumentName) +126
   System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.AddEntityToObjectStateManager(IEntityWrapper wrappedEntity, Boolean doAttach) +98
   System.Data.Entity.Core.Objects.DataClasses.EntityReference.AddEntityToObjectStateManager(IEntityWrapper wrappedEntity, Boolean doAttach) +65
   System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.AddGraphToObjectStateManager(IEntityWrapper wrappedEntity, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged, Boolean doAttach) +67
   System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach) +341
   System.Data.Entity.Core.Objects.DataClasses.EntityReference`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach) +210
   System.Data.Entity.Core.Objects.DataClasses.RelationshipManager.AddRelatedEntitiesToObjectStateManager(Boolean doAttach) +164
   System.Data.Entity.Core.Objects.ObjectContext.AddObject(String entitySetName, Object entity) +520
   System.Data.Entity.Internal.Linq.<>c__DisplayClassd.<Add>b__c() +97
   System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName) +355
   System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity) +200
   System.Data.Entity.DbSet`1.Add(TEntity entity) +130
   ValueCardPremium.Web.Controllers.<Create>d__7.MoveNext() in c:\Users\Valentine\Documents\Visual Studio 2013\Projects\ValueCardProjectPremium\ValueCardPremium.Web\Controllers\RetailerController.cs:70
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
   lambda_method(Closure , Task ) +64

person Val Okafor    schedule 12.11.2013    source источник


Ответы (2)


UserManager использует собственный DbContext для загрузки данных из базы данных. Вам нужно будет получить пользователя из того же dbContext, который вы используете для добавления ссылки. Что-то типа:

var currentUMUser = await UserManager.FindByIdAsync(User.Identity.GetUserId());
var currentUser = db.Users.Find(currentUMUser.UserID);
retailer.UserProfile = currentUser;
db.Retailers.Add(retailer);
await db.SaveChangesAsync();
return RedirectToAction("Index");

Конечно, вам придется извлекать пользователя из вашей БД, используя любой метод, который действительно работает для ваших моделей и DbContext.

person Michael Dunlap    schedule 12.11.2013
comment
Отлично спасибо. Я просто хочу добавить, что вторая строка должна быть var currentUser = db.Users.Find(currentUMUser.Id); а не UserID Большое спасибо - person Val Okafor; 12.11.2013
comment
Просто к вашему сведению, вы, вероятно, могли бы пропустить использование UserManager и просто пойти на db.Users.Find(User.Identity.GetUserId()) - person Michael Dunlap; 13.11.2013

Добавьте оператор using:

using Microsoft.AspNet.Identity;

Затем вы можете получить UserId с помощью:

var a = User.Identity.GetUserId();
person Chuck Montana    schedule 22.12.2013
comment
Опубликованный код уже содержит User.Identity.GetUserId();. - person stuartd; 23.12.2013