EF4.1:如何处理添加到Object集合中的项目

时间:2011-06-21 13:25:44

标签: c# entity-framework

我第一次使用EF4.1(所以请耐心等待我),但我无法掌握如何将新项添加到对象的子集合中然后保存对象。

例如,通过以下课程,我最初可以将TravelTicket(包含多个人)保存到我的数据库中,但只要我添加一个新人然后再尝试保存TravelTicket,我就会得到:

ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。

有人可以帮忙吗?

public class TravelTicket
{
  public int Id { get; set; }
  public string Destination { get; set; }
  public virtual List<Person> Members { get; set; }
}

public class Person
{
  public int Id { get; set; }
  public string Name{ get; set; }
}

已编辑:所有相关代码均已按要求添加:

域模型:

public class TravelTicket
{
    public int Id { get; set; }
    public string Destination { get; set; }
    public virtual ICollection<Person> Members { get; set; }
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

数据库上下文:

public class TicketContext : DbContext
{
    public TicketContext()
        : base("TicketStore")
    { }

    public DbSet<TravelTicket> TravelTickets { get; set; }
    public DbSet<Person> People { get; set; }
}

存储库(仅限相关方法):

public class TicketRepository : ITicketRepository
{

    TicketContext context = new TicketContext();

    public void InsertOrUpdate(TravelTicket quoteContainer)
    {
        if (quoteContainer.Id == default(int))
        {
            // New entity
            context.TravelTickets.Add(quoteContainer);
        }
        else
        {
            // Existing entity
            context.Entry(quoteContainer).State = EntityState.Modified;
        }
    }

    public void Save()
    {
        try
        {
            context.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                }
            }
        }
    }
}

public interface ITicketRepository
{
    void InsertOrUpdate(TravelTicket travelTicket);
    void Save();
}

消费(示例)MVC控制器代码:

public class TicketSaleController : Controller
{
    private readonly ITicketRepository ticketRepository;

    public TicketSaleController()
        : this(new TicketRepository())
    {
    }

    public TicketSaleController(ITicketRepository ticketRepository)
    {
        this.ticketRepository = ticketRepository;
    }

    public ActionResult Index()
    {
        TravelTicket ticket = new TravelTicket();
        ticket.Destination = "USA";
        List<Person> travellers = new List<Person>();
        travellers.Add(new Person { Name = "Tom" });
        travellers.Add(new Person { Name = "Dick" });
        travellers.Add(new Person { Name = "Harry" });
        ticket.Members = travellers;

        ticketRepository.InsertOrUpdate(ticket);
        ticketRepository.Save();

        Session["Ticket"] = ticket;
        return RedirectToAction("Next");
    }

    public ActionResult Next()
    {
        TravelTicket ticket = (TravelTicket)Session["Ticket"];
        ticket.Members.Add(new Person { Name = "Peter" });
        ticket.Members.Add(new Person { Name = "Paul" });
        ticketRepository.InsertOrUpdate(ticket);
        ticketRepository.Save();
        return View();
    }
}

调用“ticketRepository.InsertOrUpdate(ticket);”在“Next”方法上导致异常:

ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。

进一步编辑:如果我在保存对象后将对象从数据库中拉回来而不是从会话中拉出对象,则添加2个新人可以正常工作:

使用:     TravelTicket ticket = ticketRepository.Find(ticketId);     ticket.Members.Add(new Person {Name =“Peter”});     ticket.Members.Add(new Person {Name =“Paul”});     ticketRepository.InsertOrUpdate(票);     ticketRepository.Save();

不起作用:     TravelTicket门票=(TravelTicket)Session [“Ticket”];     ticket.Members.Add(new Person {Name =“Peter”});     ticket.Members.Add(new Person {Name =“Paul”});     ticketRepository.InsertOrUpdate(票);     ticketRepository.Save();

2 个答案:

答案 0 :(得分:1)

我需要查看您用于添加项目的代码,然后保留它们。直到那几个通用的建议。

好像你正在使用长期生活环境来做你的事情。使用短生活环境是一种很好的做法,例如:

  • 实例背景
  • 执行单个操作
  • 处理上下文

冲洗并重复您必须执行的每项操作。在遵循这一良好做法的同时,您可以间接解决您的问题。

同样,如需更具体的帮助,请发布您正在使用的代码;)

答案 1 :(得分:0)

在人物的地图类中,您可能需要执行类似这样的操作

 Property(p => p.Id)
            .StoreGeneratedPattern = StoreGeneratedPattern.Identity;