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

时间:2016-02-02 19:28:21

标签: asp.net-mvc entity-framework repository identity unit-of-work

当我尝试更新实体时,我收到了这个罕见的异常。我正在使用ASP.NET MVC 5,EF 6.1,Identity和模式库以及工作单元。 我跟着蒂姆这个很酷的 tutorial

我已经完成了4个独立项目(UI,实体,域和DataAccess)的所有工作,我将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);
        }


    }

TurnosRepository:

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;

        }




    }
}

最后,我试图完成任务的Domain类

 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();

我得到异常:“你不能定义两个对象之间的关系,因为它们与不同的ObjectContext对象”相关联,但我的代码中只有“ApplicationDbContext”。

1 个答案:

答案 0 :(得分:1)

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

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

public int PacienteId { get; set; }

转到Turno课程。

如果你的类定义得很好,你应该只需要在一侧保持关系,所以在AsignarTurno函数中代替:

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

你应该只有

t.PacienteId = p.Id;

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