MVC 3 Ninject error - asp.net-mvc

namespace NinjectDemo
{
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
public interface IValueCalculator
{
decimal ValueProducts(params Product[] products);
}
public class LinqValueCalculator : IValueCalculator
{
private IDiscountHelper discounter;
public LinqValueCalculator(IDiscountHelper discountParam)
{
discounter = discountParam;
}
public decimal ValueProducts(params Product[] products)
{
return discounter.ApplyDiscount(products.Sum(p => p.Price));
}
}
public class ShoppingCart
{
private IValueCalculator calculator;
public ShoppingCart(IValueCalculator calcParam)
{
calculator = calcParam;
}
public decimal CalculateStockValue()
{
Product[] products = {
new Product() {Name = "Kajak", Price = 275M},
new Product() {Name = "Lifejacket", Price = 48.95M},
new Product() {Name = "Soccer ball", Price = 19.50M},
new Product() {Name = "Stadium", Price = 79500M}
};
decimal totalValue = calculator.ValueProducts(products);
return totalValue;
}
}
public interface IDiscountHelper
{
decimal ApplyDiscount(decimal totalParam);
}
public class DefaultDiscountHelper: IDiscountHelper
{
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (10m / 100m * totalParam));
}
}
class Program
{
static void Main(string[] args)
{
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
ninjectKernel.Bind<IValueCalculator>().To<DefaultDiscountHelper>();//error
IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calcImpl);
Console.WriteLine("Total: {0:c}", cart.CalculateStockValue());
}
}
}
ninjectKernel.Bind().To();
write error, what could be the problem?

DefaultDiscountHelper does not implement IValueCalculator
probably you want to bind IDiscountHelper

Related

Join two tables (One to Many) using asp.net core web api

I am new at C# entity framework. I am trying to build an API, but stuck in retrieving data from relational table.
I have a Game table in MS SQL database, where GameId is the primary key. I have another table called GameCharacter, where GameCharacterId is the primary key.
In Game table GameCharacterId is foreign key. How i can get all GameCharacters on Get Games.
public class Game
{
public Game()
{
GameCharacters = new List<GameCharacter>();
}
public int GameID { get; set; }
public string Title { get; set; }
public string Platform { get; set; }
public string imgpath { get; set; }
public int ReleaseYear { get; set; }
public virtual ICollection< GameCharacter> GameCharacters { get; set; }
}
public class GameCharacter
{
[Key]
public Guid CharID { get; set; }
public string CharName { get; set; }
public string CharGame { get; set; }
public string charimgpath { get; set; }
[ForeignKey("Game")]
public int GameID { get; set; }
public virtual Game Game { get; set; }
}
public class GameController : Controller
{
private readonly GameApiDbconnect dbContext;
public GameController(GameApiDbconnect dbContext)
{
this.dbContext = dbContext;
}
[HttpGet]
public async Task<IActionResult> GetGames()
{
return Ok(await dbContext.Games.ToListAsync());
}
[HttpGet]
[Route("{GameID=guid}")]
public async Task<IActionResult> GetGame([FromRoute] Guid GameID)
{
var game = await dbContext.Games.FindAsync(GameID);
if (game == null)
{
return NotFound();
}
return Ok(game);
}
OutPut
Response body
{
"gameID": 1,
"title": "string",
"platform": "string",
"imgpath": "string",
"releaseYear": 0,
"gameCharacters": []
}
just use include
[HttpGet]
public async Task<IActionResult> GetGames()
{
var games = await dbContext.Games
.Include( g=> g.GameCharacters)
.ToListAsync();
return Ok(games);
}
[HttpGet]
public async Task<IActionResult> GetGames()
{
return Ok(from g in dbContext.Games
join c in dbContext.GameCharacters on g.GameID
equals c.GameID into Gcharacters
select new
{
GameID = g.GameID,
Title = g.Title,
Platform = g.Platform,
imgpath = g.imgpath,
ReleaseYear = g.ReleaseYear,
GameCharacters = Gcharacters.Select(gc => new {
CharID = gc.CharID, CharName = gc.CharName, CharGame =
gc.CharGame, charimgpath = gc.charimgpath }) }
) ;
}

Automapper map Dictionary<string, string> and List<string> properties to view model

I have the following view model
public class PlanDetail
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
[DisplayFormat(DataFormatString = "{0:$#.##}")]
public decimal Price { get; set; }
public string FrequencyAbbreviatedName { get; set; }
[Display(Name = "Frequency")]
public string FrequencyName { get; set; }
[Display(Name = "Events")]
public int EventLimit { get; set; }
[Display(Name = "Help Center Access")]
public bool HelpCenterAccess { get; set; }
[Display(Name = "Email Support")]
public bool EmailSupport { get; set; }
[Display(Name = "Priority Email Support")]
public bool PriorityEmailSupport { get; set; }
[Display(Name = "Phone Support")]
public bool PhoneSupport { get; set; }
public bool Active { get; set; }
public string PictureUrl { get; set; }
public bool BestValue { get; set; }
}
I am using stripe.com products and prices.
In my mapping profile class, I am able to map to the basic properties (eg Id, Name, Description, Active).
Mapper.Map<Product,PlanDetail>();
I am not sure how to map the Metadata property (Dictionary<string,string>) or the Images property (List <string>) in the stripe product object to some of the PlanDetail properties.
I created the stripe products in my seed class, and added values to the Metadata and Image properties.
public static async Task SeedStripeAsync(string stripeKey)
{
StripeConfiguration.ApiKey = stripeKey;
var productService = new ProductService();
var priceService = new PriceService();
var products = await productService.ListAsync();
var productsData = System.IO.File.ReadAllText("../Infrastructure/Data/SeedData/stripe_products.json");
var productPlans = JsonSerializer.Deserialize<List<StripeProductSeed>>(productsData);
foreach (var item in productPlans)
{
if (!products.Any(x=> x.Name.Equals(item.Name, StringComparison.InvariantCultureIgnoreCase)))
{
var productOptions = new ProductCreateOptions
{
Name = item.Name,
Description = item.Description,
Active = item.Active,
Images = new List<string>(),
Metadata = new Dictionary<string, string>()
};
productOptions.Images.Add(item.PictureUrl);
productOptions.Metadata.Add("EventLimit", item.EventLimit.ToString());
productOptions.Metadata.Add("HelpCenterAccess", item.HelpCenterAccess.ToString());
productOptions.Metadata.Add("EmailSupport", item.EmailSupport.ToString());
productOptions.Metadata.Add("PriorityEmailSupport", item.PriorityEmailSupport.ToString());
productOptions.Metadata.Add("PhoneSupport", item.PhoneSupport.ToString());
productOptions.Metadata.Add("BestValue", item.BestValue.ToString());
var newProduct = await productService.CreateAsync(productOptions);
var priceOptions = new PriceCreateOptions
{
UnitAmountDecimal = item.Price,
Currency = "usd",
Recurring = new PriceRecurringOptions()
{
Interval = item.Interval,
IntervalCount = (long)item.IntervalCount
},
Product = newProduct.Id
};
await priceService.CreateAsync(priceOptions);
}
}
}
I would like to map the stripe Product Metadata properties such as EventLimit, HelpCenterAccess, EmailSupport, PriorityEmailSupport, PhoneSupport, and BestValue to their respective counterparts in the PlanDetail view model.
In addition, I would like to map the stripe Product Image property to the PictureUrl property in the PlanDetail view model.
Any ideas or suggestions how to use automapper for theses properties would be much appreciated.
Here's what I assume
// Just demo class
public class StripeProductSeed
{
public string PictureUrl { get; set; }
public int EventLimit { get; set; }
public bool HelpCenterAccess { get; set; }
public bool EmailSupport { get; set; }
public bool PriorityEmailSupport { get; set; }
public bool PhoneSupport { get; set; }
public bool BestValue { get; set; }
public List<string> ExtractImages() => new() { PictureUrl };
public Dictionary<string, string> ExtractMetaData() => new()
{
{nameof(EventLimit), EventLimit.ToString()},
{nameof(HelpCenterAccess), HelpCenterAccess.ToString()},
{nameof(EmailSupport), EmailSupport.ToString()},
{nameof(PriorityEmailSupport), PriorityEmailSupport.ToString()},
{nameof(PhoneSupport), PhoneSupport.ToString()},
{nameof(BestValue), BestValue.ToString()}
};
}
The map should be:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<StripeProductSeed, PlanDetail>()
.ForMember(dst => dst.Images, x => x.MapFrom(src => src.ExtractImages()))
.ForMember(dst => dst.Metadata, x => x.MapFrom(src => src.ExtractMetaData()));
}
}

how to access elements of a list in controller

Entities
public class Employee
{
public long BusinessUnitID{ get; set; }
public long EmployeeID { get; set; }
public long InfoTypeID { get; set; }
public string EmployeeName { get; set; }
public List<ContactData> ContactDetails{ get; set; }
}
public class ContactData
{
public string ContactTypeName { get; set; }
public string ContactValue { get; set; }
}
Model
Public class EmployeeDetails
{
public long BusinessUnitID { get; set; }
public List<EmployeeData> EmployeeInfo { get; set;}
public List<ContactInfo> Contacts { get; set; }
}
public class EmployeeData
{
public long EmployeeID { get; set;}
public string EmployeeName { get; set;}
}
Public class ContactInfo
{
public string ContactName { get; set; }
public long ContactValue { get; set; }
}
Controller
public ActionResult Update(long BusinessUnitID=2)
{
if (Session[Constants.Session_IsAdmin] != null && Convert.ToBoolean(Session[Constants.Session_IsAdmin]))
{
EmployeeDetails employeeDetails = new EmployeeDetails();
List<Employee> employee = GetEmployeeById(Convert.ToInt64(BusinessUnitID));
List<EmployeeData> lstEmployeeData = new List<EmployeeData>();
List<ContactInfo> lstContactInfo = new List<OptionDetails>();
var ID = employee.Select(x => x.BusinessUnitID).ToList();
foreach(var item in employee.Where(x => x.BusinessUnitID == BusinessUnitID))
{
EmployeeData employeeData = new EmployeeData();
employeeData.EmployeeID = item.EmployeeID;
employeeData.EmployeeName = item.EmployeeName;
foreach (var local in employee.Where(q => q.EmployeeID == employeeData.EmployeeID))
{
//ContactInfo contactInfo = new ContactInfo();
//contactInfo.ContactName = local.ContactDetails.Select(p => p.ContactName).ToString();
//contactInfo.ContactValue = local.ContactDetails.Select(s => s.ContactValue).ToString();
}
lstEmployeeData.Add(employeeData);
}
return View(EmployeeDetails);
}
else
{
return RedirectToAction("Login");
}
}
Here I'm getting a list Employee in which i have below properties and a list ContactDetails which is a list containing atleast 3 elements for its properties. For eg 3 types of ContactTypeName and ContactValue as Home: 000000000, work: 9999999, mobile: 8888888. For a businessUnitid i got all employeeid for a perticular EmployeeID i want contact details but i'm unable to get or 3 contactvalue and contactname. In list Employee there is list ContactDetails in which there would be 3 or 5 contact numbers. I don't know how must i assign it to a list.
As employee can have multiple contact details, you need to add contact detail list property to EmployeeData class
Model classes :
Public class EmployeeDetails
{
public EmployeeDetails()
{
EmployeeInfo = new List<EmployeeData>();
}
public long BusinessUnitID { get; set; }
public List<EmployeeData> EmployeeInfo { get; set;}
}
public class EmployeeData
{
public EmployeeData()
{
Contacts = new List<ContactInfo>();
}
public long EmployeeID { get; set;}
public string EmployeeName { get; set;}
public List<ContactInfo> Contacts { get; set; }
}
Public class ContactInfo
{
public string ContactName { get; set; }
public long ContactValue { get; set; }
}
Then it's easy to pass the data of employees with multiple contacts
public ActionResult Update(long BusinessUnitID=2)
{
if (Session[Constants.Session_IsAdmin] != null && Convert.ToBoolean(Session[Constants.Session_IsAdmin]))
{
List<Employee> employees = GetEmployeeById(Convert.ToInt64(BusinessUnitID));
List<EmployeeData> lstEmployeeData = new List<EmployeeData>();
foreach(var item in employee.Where(x => x.BusinessUnitID == BusinessUnitID))
{
EmployeeData employeeData = new EmployeeData();
employeeData.EmployeeID = item.EmployeeID;
employeeData.EmployeeName = item.EmployeeName;
foreach (var contact in employee.ContactDetails)
{
ContactInfo contactInfo = new ContactInfo();
contactInfo.ContactName = contact.ContactName;
contactInfo.ContactValue = contact.ContactValue;
employeeData.Contacts.Add(contactInfo);
}
lstEmployeeData.Add(employeeData);
}
EmployeeDetails empDetails = new EmployeeDetails();
empDetails.EmployeeInfo = lstEmployeeData;
return View(empDetails);
}
else
{
return RedirectToAction("Login");
}
}

How to eager load (include) a private field collection with a public read only property

System.NotSupportedException : Collection is read-only.
at System.ThrowHelper.ThrowNotSupportedException(ExceptionResource resource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.ClrICollectionAccessor`3.Add(Object instance, Object value)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.AddToCollection(InternalEntityEntry entry, INavigation navigation, IClrCollectionAccessor collectionAccessor, Object value)
public class Student
{
public int Id {get; private set;}
private List<StudentProgress> _progresses;
protected Student()
{
_progresses = new List<StudentProgress>();
}
public IEnumerable<StudentProgress> Progresses =>_progresses.AsReadOnly();
}
public class StudentProgress
{
public int Id {get; private set;}
public int ProgressStatusId { get; private set; }
public int Year { get; private set; }
public Grade Grade { get; private set; }
public int CourseId { get; private set; }
public StudentProgress(Grade grade, int year, int courseId, int progress)
{
ProgressStatusId = progress;
Year = year;
Grade = grade;
CourseId = courseId;
}
}
public class StudentEntityTypeConfiguration : IEntityTypeConfiguration<Student>
{
public void Configure(EntityTypeBuilder<Student> studentConfiguration)
{
studentConfiguration.HasKey(x => x.Id);
studentConfiguration.Ignore(x => x.DomainEvents);
studentConfiguration.Metadata.FindNavigation(nameof(Student.Progresses))
.SetPropertyAccessMode(PropertyAccessMode.Field);
}
}
public class Context : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new StudentEntityTypeConfiguration());
}
}
this is where I'm getting the error (Repository):
public async Task<Student> FindAsync(int identity)
{
var student = await _context.Set<Student>()
.Include(x=>x.Progresses) // this line is generating the error
.Where(b => b.Id == identity)
.SingleOrDefaultAsync();
return student;
}
I attempted to change the way you're getting _progresses in my code:
public class Student
{
public int Id {get; private set;}
private List<StudentProgress> _progresses;
protected Student()
{
_progresses = new List<StudentProgress>();
}
public IEnumerable<StudentProgress> Progresses =>_progresses; // changed from AsReadOnly()
}

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

I am getting this rare exception when I am trying to update an entity. I am working with ASP.NET MVC 5, EF 6.1, Identity and the patterns repository and unit of work.
I followed this cool tutorial from Tim.
I have all the work done in 4 separate projects (UI, Entities, Domain and DataAccess), I included Tim solution to use Users and roles.
My Entities:
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));
}
}
}
}
}
My Repositories:
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);
}
}
}
User repository:
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);
}
}
}
My Context:
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());
}
}
}
My Unit Of Work
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;
}
}
}
And Finally, the Domain class where I am trying to get things done
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;
}
The problem occurs in line unitofwork.SaveChanges();
I get the exception: "You can not define the relationship between two objects because they are associated with different ObjectContext objects" but I only have "ApplicationDbContext" in my code.
The problem is that you have one type which is ApplicationDbContext, but there are two instances of that context. One instantiated to fetch Pacient p and another one for Turno t.
Where is the AsignarTurno(Paciente p, Turno t) called from?
If this is code first you should add
public int PacienteId { get; set; }
to class Turno.
If your classes are well define you should only need to persist the relation on one side, so in the AsignarTurno function instead of:
t.Paciente = p;
p.Turnos.Add(t);
you should only have
t.PacienteId = p.Id;
This would do what you need, assuming that p and t both exist the database.

Resources