您不能定义两个对象之间的关系,因为它们与不同的 ObjectContext 对象相关联

You can not define the relationship between two objects because they are associated with different ObjectContext objects

我在尝试更新实体时遇到了这个罕见的异常。我正在使用 ASP.NET MVC 5、EF 6.1、Identity 和模式存储库以及工作单元。 我关注了蒂姆 tutorial 的这篇酷

我在 4 个单独的项目(UI、实体、域和数据访问)中完成了所有工作,我包括了使用用户和角色的 Tim 解决方案。

我的实体:

public class Turno : IEntity
{

    public Turno()
    {
        //Medico = new Medico();
        //Consultorio = new Consultorio();
    }

    public Int64 Id { get; set; }
    [Required]
    public DateTime Fecha { get; set; }
    [Required]
    [StringLength(10)]
    public string Hora { get; set; }
    [Required]
    public Medico Medico { get; set; }
    [Required]
    public Consultorio Consultorio { get; set; }

    [Required]
    public EstadoTurno Estado { get; set; }

    public virtual Paciente Paciente { get; set; }


}


namespace TurnosMedicos.Entities
{
    [Table("Medicos")]
    public class Medico: Persona
    {
        public Medico()
        {
            Especialidades = new List<Especialidad>();
            TurnosDisponibles = new List<Turno>();
            Consultorios = new List<Consultorio>();
            Telefonos = new List<Telefono>();
            PlanesAtendidos = new List<PrepagaPlan>();
        }

        [Required]
        [StringLength(10)]
        public string Matricula { get; set; }

        [Required]
        public decimal PrecioTurno { get; set; }

        public virtual List<Especialidad> Especialidades { get; set; }
        public virtual List<Turno> TurnosDisponibles { get; set; }

        public virtual List<Consultorio> Consultorios { get; set; }


        public List<PrepagaPlan> PlanesAtendidos { get; set; }


        public override string ToString()
        {
            return Apellido + ", " + Nombres;
        }
    }
}


namespace TurnosMedicos.Entities
{
    public class Paciente: Persona
    {
        public Paciente()
        {
            HistoriaClinica = new List<Consulta>();
            Turnos = new List<Turno>();
            Telefonos = new List<Telefono>();
            PlanesSalud = new List<PrepagaPlan>();
            TurnosAusentes = new List<TurnoInformadoAusente>();
        }


        public virtual List<TurnoInformadoAusente> TurnosAusentes { get; set; }

        public virtual List<Consulta> HistoriaClinica { get; set; }

        public virtual List<Turno> Turnos { get; set; }

        public override string ToString()
        {
            return Apellido + ", " + Nombres;
        }

        public List<PrepagaPlan> PlanesSalud { get; set; }

        public PrepagaPlan PlanPredeterminado()
        {
            if(PlanesSalud.Count()>0)
            {
                return PlanesSalud[0];
            }

            return null;
        }


        public string TelefonosRapido()
        {
            System.Text.StringBuilder tel = new System.Text.StringBuilder();

            foreach(var t in this.Telefonos)
            {
                tel.Append(t.Numero + " (" +  t.Tipo + ")");
                tel.AppendLine();
            }

            return tel.ToString();
        }

        /// <summary>
        /// Porcentaje de Asistencia
        /// </summary>
        [NotMapped]
        public decimal Ranking
        {
            get{
                if (TurnosAusentes.Count == 0)
                {
                         return 100;
                }
                else{
                    return  (100 - (Decimal.Divide(TurnosAusentes.Count, Turnos.Count) * 100));
                }
            }
        }


    }
}

我的存储库:


 public class MedicosRepository: Repository<Medico> //, IMedicoRepository
    {

        internal MedicosRepository(ApplicationDbContext context)
            : base(context)
        {
        }

        public IQueryable<Medico> Find(System.Linq.Expressions.Expression<Func<Medico, bool>> predicate)
        {
            return Set.Where(predicate);
        }

        public override List<Medico> GetAll()
        {
            return Set.Include("Telefonos")
                      .Include("PlanesAtendidos")
                      .Include("Consultorios")
                      .Include("Consultorios.Telefonos")
                      .Include("TurnosDisponibles.Paciente.Telefonos")
                      .ToList();
        }

        public IQueryable<Medico> FindAll()
        {
            return Set.Include("Telefonos")
                      .Include("PlanesAtendidos")
                      .Include("Consultorios")
                      .Include("Consultorios.Telefonos")
                      .Include("TurnosDisponibles.Paciente.Telefonos");

        }

        public override Medico FindById(object id)
        {
            Int64 Id = Int64.Parse(id.ToString());

            return Set.Include("Telefonos")
                                    .Include("Consultorios")
                                    .Include("Consultorios.Telefonos")
                                    .Include("PlanesAtendidos")
                                    .Include("TurnosDisponibles.Paciente.Telefonos")
                                    .Single(o => o.Id == Id);
        }


    }

Turnos 存储库:

namespace TurnosMedicos.DataAccess.Repositories
{
    internal class TurnosRepository: Repository<Turno>
    {
        public TurnosRepository(ApplicationDbContext context): base(context)
        {
        }

        public override List<Turno> GetAll()
        {
            return Set.Include("Medico")
                        .Include("Paciente")
                        .Include("Consultorio").ToList();   
        }


        public override Turno FindById(object id)
        {
            Int64 Id = Int64.Parse(id.ToString());

            return Set.Include("Medico")
                      .Include("Paciente")
                      .Include("Consultorio")
                      .Single(o => o.Id == Id);

        }


    }
}

用户资料库:

namespace TurnosMedicos.DataAccess.Repositories
{
    internal class UserRepository : Repository<User>, IUserRepository
    {
        internal UserRepository(ApplicationDbContext context)
            : base(context)
        {
        }

        public User FindByUserName(string userName)
        {
            return Set.Include("Medico")
                      .Include("Paciente")
                      .FirstOrDefault(x => x.UserName == userName);
        }

        public Task<User> FindByUserNameAsync(string userName)
        {
            return Set.FirstOrDefaultAsync(x => x.UserName == userName);
        }

        public Task<User> FindByEmailAsync(System.Threading.CancellationToken cancellationToken, string email)
        {
            return Set.FirstOrDefaultAsync(x => x.Email == email, cancellationToken);
        }


        public User FindByEmail(string email)
        {
            return Set.Include("Medico")
                      .Include("Medico.Telefonos")
                      .Include("Medico.Especialidades")
                      .Include("Medico.TurnosDisponibles")
                      .Include("Medico.Consultorios")
                      .Include("Medico.PlanesAtendidos")
                      .Include("Paciente")
                      .Include("Paciente.Turnos")
                      .Include("Paciente.PlanesSalud")
                      .Include("Paciente.HistoriaClinica")
                      .Include("Paciente.TurnosAusentes")
                      .Include("Paciente.Telefonos")
                      .Include("Roles")
                      .FirstOrDefault(u => u.Email == email);
        }
    }
}

我的背景:

namespace TurnosMedicos.DataAccess
{
    internal class ApplicationDbContext : DbContext
    {
        internal ApplicationDbContext(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {
        }

        public ApplicationDbContext(): base("TurnosMedicosCn")
        {

        }

        public IDbSet<User> Users { get; set; }
        public IDbSet<Role> Roles { get; set; }
        public IDbSet<ExternalLogin> Logins { get; set; }

        public DbSet<Paciente> Pacientes { get; set; }
        public DbSet<Medico> Medicos { get; set; }
        public DbSet<Turno> Turnos { get; set; }
        public DbSet<Consulta> Consultas { get; set; }
        public DbSet<Consultorio> Consultorios { get; set; }
        public DbSet<Especialidad> Especialidades { get; set; }
        public DbSet<Prepaga> Prepagas { get; set; }
        public DbSet<PrepagaPlan> Planes { get; set; }
        public DbSet<Registro> RegistrosFacturacion { get; set; }
        public DbSet<Empresa> Empresas { get; set; }
        public DbSet<Recomendado> Recomendados { get; set; }



        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new UserConfiguration());
            modelBuilder.Configurations.Add(new RoleConfiguration());
            modelBuilder.Configurations.Add(new ExternalLoginConfiguration());
            modelBuilder.Configurations.Add(new ClaimConfiguration());
        }
    }
}

我的工作单位

namespace TurnosMedicos.DataAccess
{
    public class SQLUnitOfWork: IUnitOfWork
    {


        private readonly ApplicationDbContext _context;

        PacientesRepository _pacientes = null;
        //MedicosRepository  _medicos = null;
        IRepository<Medico> _medicos = null;
        TurnosRepository _turnos = null;
        EspecialidadRepository _especialidades = null;
        PrepagasRepository _prepagas = null;
        PrepagaPlanesRepository _planes = null;
        RegistrosFacturacionRepository _registroFacturacion = null;
        RecomendadosRepository _recomendados = null;
        private IExternalLoginRepository _externalLoginRepository;
        private IRoleRepository _roleRepository;
        private IUserRepository _userRepository;


        public SQLUnitOfWork(string nameOrConnectionString)
        {
            _context = new ApplicationDbContext(nameOrConnectionString);
        }

        public IRepository<Turno> Turnos
        {
            get { return _turnos ?? (_turnos = new TurnosRepository(_context)); }

        }

        public IRepository<Paciente> Pacientes
        {
            get
            {
                if(_pacientes==null)
                {
                    _pacientes = new PacientesRepository(_context);
                }
                return _pacientes;
            }

        }

         public IRepository<Medico>  Medicos
        {
            get { return _medicos ?? (_medicos = new MedicosRepository(_context)); }
        }

        public IRepository<Especialidad> Especialidades
        {
            get
            {
                if (_especialidades == null)
                {
                    _especialidades = new EspecialidadRepository(_context);
                }
                return _especialidades;
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public IRepository<Prepaga> Prepagas {
                get {
                    if (_prepagas == null)
                    {
                        _prepagas = new PrepagasRepository(_context);
                    }
                    return _prepagas;
                }
            set { throw new NotImplementedException(); }
        }

        public IRepository<PrepagaPlan> Planes { 
                            get 
                            {
                                if (_planes == null)
                                {
                                    _planes = new PrepagaPlanesRepository(_context);
                                }
                                return _planes;
                            }
        }

        public IRepository<Registro> RegistrosFacturacion
        {
            get
            {
                if(_registroFacturacion == null)
                {
                    _registroFacturacion = new RegistrosFacturacionRepository(_context);
                }
                return _registroFacturacion;
            }
        }

        public IRepository<Recomendado> Recomendados
        {
            get
            {
                if (_recomendados == null)
                {
                    _recomendados = new RecomendadosRepository(_context);
                }
                return _recomendados;
            }
        }



        public IExternalLoginRepository ExternalLoginRepository
        {
            get { return _externalLoginRepository ?? (_externalLoginRepository = new ExternalLoginRepository(_context)); }
        }

        public IRoleRepository RoleRepository
        {
            get { return _roleRepository ?? (_roleRepository = new RoleRepository(_context)); }
        }

        public IUserRepository UserRepository
        {
            get { return _userRepository ?? (_userRepository = new UserRepository(_context)); }
        }




        public int SaveChanges()
        {
            try
            {
                return _context.SaveChanges();
            }
            catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
            {
                Exception raise = dbEx;
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        string message = string.Format("{0}:{1}",
                            validationErrors.Entry.Entity.ToString(),
                            validationError.ErrorMessage);
                        raise = new InvalidOperationException(message, raise);
                    }
                }
                throw raise;
            }

        }

        public Task<int> SaveChangesAsync()
        {
            try
            {
                return _context.SaveChangesAsync();
            }
            catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
            {
                Exception raise = dbEx;
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        string message = string.Format("{0}:{1}",
                            validationErrors.Entry.Entity.ToString(),
                            validationError.ErrorMessage);
                        raise = new InvalidOperationException(message, raise);
                    }
                }
                throw raise;
            }

        }

        public Task<int> SaveChangesAsync(System.Threading.CancellationToken cancellationToken)
        {
            return _context.SaveChangesAsync(cancellationToken);
        }

        public void Dispose()
        {
            _externalLoginRepository = null;
            _roleRepository = null;
            _userRepository = null;
            _turnos = null;
            _pacientes = null;
            _especialidades = null;
            _planes = null;
            _prepagas = null;
            _recomendados = null;
            _registroFacturacion = null;

        }




    }
}

最后,域 class 我正在尝试完成工作

 IUnitOfWork unitofwork = null;
    IRepository<Paciente> repositoryPacientes = null;

    //IMedicoRepository repositoryMedicos = null;
    IRepository<Medico> repositoryMedicos = null;
    IRepository<Turno> repositoryTurnos = null;
    IRepository<Especialidad> repositoryEspecialidad = null;
    IRepository<Registro> repositoryRegistroFacturacion = null;
    IRepository<Recomendado> repositoryRecomendados = null;

    public TurnosManager(IUnitOfWork _unitOfWork)
    {
        unitofwork = _unitOfWork;
        repositoryPacientes = unitofwork.Pacientes;
        repositoryMedicos = unitofwork.Medicos;
        repositoryTurnos = unitofwork.Turnos;
        repositoryEspecialidad = unitofwork.Especialidades;
        repositoryRegistroFacturacion = unitofwork.RegistrosFacturacion;
        repositoryRecomendados = unitofwork.Recomendados;
    }

    private bool AsignarTurno(Paciente p, Turno t)
    {
        if(t.Fecha.Date < DateTime.Now.Date)
        {
            throw new TurnoInvalidoException("No se puede seleccionar un turno para una fecha en el pasado.");
        }
        // Ver tema de la hora para la fecha actual

        t.Estado = EstadoTurno.Reservado;
        t.Paciente = p;
        p.Turnos.Add(t);
        //repositoryTurnos.Update(t);
        unitofwork.SaveChanges();

        string planMedico = "Privado";

        if (p.PlanesSalud.Count > 0)
        {
            planMedico = p.PlanesSalud[0].NombrePlan;
        }


        RegisstrarParaFacturacion(t, planMedico);

        ReservaVM obj = new ReservaVM();
        obj.Paciente = p;
        obj.MedicoSeleccionado = t.Medico;
        obj.TurnoSeleccionado = t;

        EnviarEmail(obj);
        return true;
    }

问题出现在unitofwork.SaveChanges();

我得到异常:"You can not define the relationship between two objects because they are associated with different ObjectContext objects" 但我的代码中只有 "ApplicationDbContext"。

问题是您有一种类型,即 ApplicationDbContext,但该上下文有两个实例。一个实例化为获取 Pacient p,另一个实例化为 Turno t。 AsignarTurno(Paciente p, Turno t) 从哪里调用?

如果这是代码,您应该先添加

public int PacienteId { get; set; }

转class转。

如果您的 classes 定义良好,您应该只需要在一侧保持关系,因此在 AsignarTurno 函数中而不是:

t.Paciente = p;
p.Turnos.Add(t);

你应该只有

t.PacienteId = p.Id;

假设 p 和 t 都存在于数据库中,这将满足您的需要。