I can't seem to figure out what is going wrong here, I have configured AutoMapper as follows
services.AddAutoMapper(typeof(MetingenView), typeof(Meting));
And in the controller like this:
public MetingenController(IMapper mapper)
{
this._mapper = mapper;
}
After, I use it like this:
var entity = await this.Context.MetingenView.AsNoTracking().FirstOrDefaultAsync(g =>g.IdMeting == key);
if (entity == null)
{
return NotFound();
}
data.Patch(entity);
var meting = await this.Context.Meting.FirstOrDefaultAsync(m => m.IdMeting == key);
this._mapper.Map(entity, meting);
Then the error rolls out:
AutoMapper.AutoMapperMappingException: Missing type map configuration
or unsupported mapping.
EDIT:
Here are the Meting, and MetingenView classes:
public partial class Meting
{
public int IdMeting { get; set; }
public int IdKoeling { get; set; }
public int IdWerknemer { get; set; }
public int IdGebouw { get; set; }
public int Temperatuur { get; set; }
public DateTime AfgenomenTijd { get; set; }
public string ProductNaam { get; set; }
public string Actie { get; set; }
public DateTime? DatumOntstaan { get; set; }
public DateTime? DatumMutatie { get; set; }
public int IndVerwijderd { get; set; }
public DateTime? DatumVerwijderd { get; set; }
public virtual Gebouw IdGebouwNavigation { get; set; }
public virtual Koeling IdKoelingNavigation { get; set; }
public virtual Werknemer IdWerknemerNavigation { get; set; }
}
public partial class MetingenView
{
[Key]
public int IdKlant { get; set; }
public string Locatie { get; set; }
public string SoortKoeling { get; set; }
public int IdMeting { get; set; }
public int IdKoeling { get; set; }
public int IdWerknemer { get; set; }
public int IdGebouw { get; set; }
public int Temperatuur { get; set; }
public string Actie { get; set; }
public string ProductNaam { get; set; }
public DateTime AfgenomenTijd { get; set; }
}
I think the mapping between Meting and MetingenView is not configured in AutoMapper. If you use Asp.Net Core, you could create a profile.
public class MetingProfile : Profile
{
public MetingProfile()
{
CreateMap<MetingenView, Meting>();
}
}
This would create a default mapping that two types have the same property. If you want to config property mapping manually, Function ForMember() would be used.
For example, if you wish that the property MetingenView.IdGebouw maps Meting.IndVerwijderd, you can code this:
CreateMap<MetingenView, Meting>()
.ForMember(dest=>dest.IdGebouw, opt=>opt.MapFrom(src=>src.IndVerwijderd));
Related
First of all I get an error when I try to access the data from this column and I don't know what the reason is.
I'm working with .NET 6 and EF Core.
I have this class :
namespace Core.Entities;
public class Usuario
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int IdTecnico { get; set; }
public string Nombre { get; set; }
public string Apellido1 { get; set; }
public string Apellido2 { get; set; }
public string NIF { get; set; }
public string EmailPersonal { get; set; }
public string EmailCorporativo { get; set; }
public string Direccion { get; set; }
public string Telefono1 { get; set; }
public string Telefono2 { get; set; }
public DateTime FechaRegistro { get; set; }
public DateTime? FechaAltaEmpresa { get; set; }
public DateTime? FechaBajaEmpresa { get; set; }
public string WebContrasena { get; set; }
public int WebRol { get; set; }
public int SeguimientNotificacion { get; set; }
public DateTime? SeguimientoFecha { get; set; }
public int? SeguimientoIntervalo { get; set; }
public decimal? EmpresaTarifa { get; set; }
public int? EmpresaCategoria { get; set; }
public string ClienteCuenta { get; set; }
public int? ClienteCategoria { get; set; }
public int? ClienteNivel { get; set; }
public string RedmineAPIKey { get; set; }
public int? RedmineIdProyecto { get; set; }
}
Table in SQL Server:
Class entity is used by this dbcontext this way:
namespace Infrastructure.Data;
public class UsuariosContext : DbContext
{
public UsuariosContext(DbContextOptions<UsuariosContext> options) : base(options)
{
}
public DbSet<Core.Entities.Usuario> Usuarios { get; set; }
}
With dependency injection, I inject it the dbcontext into this class that implements generic operations of crud:
namespace Infrastructure.Repositories;
public class UsuarioRepository : IRepository<Core.Entities.Usuario, int>
{
UsuariosContext _context;
public UsuarioRepository(UsuariosContext context)
{
_context = context;
}
public async Task<IReadOnlyList<Usuario>> GetAllAsync()
{
// I get an error because _context.set() operation is null
return await _context.Set<Usuario>().ToListAsync();
}
}
So the "presentation layer" calls this operation and I get an error:
That's because _context.set() operation is null as you see, but why is null, did I miss something?
I am doing EXACTLY the same with other db columns and it works perfectly.
DI Config:
Entity properties dont allow null, you should delete allow null values in fields in database or add ? (null operator) on model
I am using code first approach with Entity Framework 6. Three of my model classes implements inheritance and each of these model has collection which also implement inheritance. I am using TPH inheritance strategy. Everything works fine and I can insert/update with no problem at all. However, I get when I try to read data from the repo. The I get is shown below.
I have include my models, entity configuration and the line that throws this exception:
The include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the select operator for collection navigation properties
Code:
public abstract class OrderSup
{
public OrderSup()
{
DetailOrderSups = new HashSet<DetailOrderSup>();
}
public int Id { get; set; }
public string Description { get; set; }
public decimal AmountPaid { get; set; }
public DateTime DateEntered { get; set; }
public string CusSupCode { get; set; }
public decimal NetAmount { get; set; }
public decimal TaxAmount { get; set; }
public string DespatchSatus { get; set; }
public string Reference { get; set; }
}
public abstract class DetailOrderSup
{
[Key, Column(Order = 0)]
public virtual int OrderId { get; set; }
[Key, Column(Order = 1)]
public virtual int ProductId { get; set; }
public virtual Product OrderedProducts { get; set; }
public InvoiceType InvoiceType { get; set; }
public virtual OrderSup OrderSup { get; set; }
}
public class Order : OrderSup
{
public int SalesOrderNumber { get; set; }
public InvoiceType InvoiceType { get; set; }
}
public class PurchaseOrder : OrderSup
{
public string OrderStatus { get; set; }
//public string AlocationStatus { get; set; }
public int InvoiceNumber { get; set; }
}
public class PurchaseOrderDetails : DetailOrderSup
{
public bool IsOrderPaid { get; set; }
public decimal Outstanding { get; set; }
public decimal AmountPaid { get; set; }
public bool IsDisputed { get; set; }
}
public class OrderDetails: DetailOrderSup
{
public bool IsOrderPaid { get; set; }
public decimal Outstanding { get; set; }
}
public IEnumerable<PurchaseOrder> GetPurchaseOrders()
{
// THIS IS LINE THAT THROWS EXCEPTION
return this.AppContext.Orders.OfType<PurchaseOrder>()
.Include(o => o.DetailOrderSups.OfType<PurchaseOrderDetails>());
}
class OrderSupConfiguration : EntityTypeConfiguration<OrderSup>
{
public OrderSupConfiguration()
{
HasMany(p => p.DetailOrderSups)
.WithRequired(o => o.OrderSup)
.HasForeignKey(o => o.OrderId);
}
}
Please what am I doing wrong?
Thanks in advance for your assistance
I'm trying to create a view, which previously got an ID, which is working fine(checked in debugger, ID is correct), to invoke a method:
public ActionResult DetaljiNarudzbe(int id)
{
DetaljiNarudzbeViewModel model = new DetaljiNarudzbeViewModel();
model.Narudzba = ctx.Naruzbee.Where(x => x.Id == id).First();
model.StatusNarudzbe = ctx.StatusiNarudzbi.Where(x => x.Id == model.Narudzba.StatusNarudzbeId).FirstOrDefault();
model.Primaoc = ctx.Primaoci.Where(x => x.Id == model.Narudzba.PrimaocId).FirstOrDefault();
model.Adresa = ctx.Adrese.Where(x => x.Id == model.Narudzba.AdresaId).FirstOrDefault();
model.Grad = ctx.Gradovi.Where(x => x.Id == model.Adresa.GradId).FirstOrDefault();
model.StavkeNarudzbe = ctx.StavkeNarudzbi.Where(x => x.Narudzbe_Id == id).ToList();
model.Klijent = ctx.Klijenti.Where(x => x.Id == model.Narudzba.KlijentId).FirstOrDefault();
model.Korisnik = ctx.Korisnici.Where(x => x.Id == model.Klijent.KorisnikId).FirstOrDefault();
return View("DetaljiNarudzbe", model);
}
However, it keeps crashing at this part
model.StavkeNarudzbe = ctx.StavkeNarudzbi.Where(x => x.Narudzbe_Id == id).ToList();
It throws an exception, because for some reason, I think the context created another column called Narudzbe_Id1, which can't be null.
https://imgur.com/a/UFxXB - Image of the given exception
Further proof that it's an issue with dbcontext:
https://imgur.com/a/KEOe3
The extra column doesn't appear in the database on the SQL server's side, where I'm getting the data from.
If it helps, I'm posting the other relevant classes below:
public class StavkaNarudzbe : IEntity
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
public string Naziv { get; set; }
public int Tezina { get; set; }
public double Cijena { get; set; }
public int Narudzbe_Id { get; set; }
public virtual Narudzbe Narudzbe { get; set; }
}
public class MojKontekst : DbContext
{
public MojKontekst() : base("DostavaConnString")
{
}
public DbSet<Adresa> Adrese { get; set; }
public DbSet<Grad> Gradovi { get; set; }
public DbSet<DetaljiVozila> DetaljiVozilaa { get; set; }
public DbSet<Klijent> Klijenti { get; set; }
public DbSet<Korisnik> Korisnici { get; set; }
public DbSet<Kurir> Kuriri { get; set; }
public DbSet<Kvar> Kvarovi { get; set; }
public DbSet<Obavijest> Obavijesti { get; set; }
public DbSet<Narudzbe> Naruzbee { get; set; }
public DbSet<Posiljka> Posiljke { get; set; }
public DbSet<Prelazi> Prelazii { get; set; }
public DbSet<Primaoc> Primaoci { get; set; }
public DbSet<Skladiste> Skladista { get; set; }
public DbSet<StatusNarudzbe> StatusiNarudzbi { get; set; }
public DbSet<StavkaNarudzbe> StavkeNarudzbi { get; set; }
public DbSet<Vozilo> Vozila { get; set; }
public DbSet<VrstaVozila> VrsteVozila { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
public class DetaljiNarudzbeViewModel
{
public Klijent Klijent;
public Korisnik Korisnik;
public Narudzbe Narudzba;
public List<StavkaNarudzbe> StavkeNarudzbe;
public StatusNarudzbe StatusNarudzbe;
public Primaoc Primaoc;
public Adresa Adresa;
public Grad Grad;
}
public class Narudzbe : IEntity
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
public string SifraNarudzbe { get; set; }
public DateTime DatumNarudzbe { get; set; }
public bool Osigurano { get; set; }
public bool BrzaDostava { get; set; }
public int BrojPaketa { get; set; }
public int KlijentId { get; set; }
public virtual Klijent Klijent { get; set; }
public int AdresaId { get; set; }
public virtual Adresa Adresa { get; set; }
public Nullable<int> PosiljkaId { get; set; }
public virtual Posiljka Posiljka { get; set; }
public int StatusNarudzbeId { get; set; }
public virtual StatusNarudzbe StatusNarudzbe{ get; set; }
public int PrimaocId { get; set; }
public virtual Primaoc Primaoc { get; set; }
public Nullable<System.DateTime> VrijemeIsporuke { get; set; }
public int CijenaNarudzbe { get; set; }
}
Exception Text: Invalid column name Narudzbe_Id1
This is Entity Framework trying to follow it's standard naming conventions for relationship columns.
See: https://msdn.microsoft.com/en-us/library/jj819164(v=vs.113).aspx for more information this.
As you are using non-standard names for your foreign key columns (i.e. Narudzbe_Id should be NarudzbeId) you'll need to let EF know how to link up your models. Either rename the properties of your classes to follow this naming convention, or use Data Annotations to explicitly tell EF about your relationships.
For example, try adding a ForeignKey attribute (found in the System.Componentmodel.Dataannotations.Schema namespace) like so:
public class StavkaNarudzbe : IEntity
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
public string Naziv { get; set; }
public int Tezina { get; set; }
public double Cijena { get; set; }
public int Narudzbe_Id { get; set; }
[ForeignKey("Narudzbe_Id")]
public virtual Narudzbe Narudzbe { get; set; }
}
I am trying to map a model to a view, but I receive the error above when I am trying to display all my elements, since Automapper doesn't recognize the IEnumerable I think. I receive the error when I am trying to map FixedAssets to FixedAssetsView and FixedAssetsView to FixedAssets.
Here are the objects I am trying to map:
FixedAssets
public class FixedAssets : IEntityBase
{
public int ID { get; set; }
public string name { get; set; }
public virtual ICollection<Category> category { get; set; }
public string serialNo { get; set; }
public string provider { get; set;
public DateTime acquisitionDate { get; set; }
public DateTime warrantyEnd { get; set; }
public int inventoryNo { get; set; }
public string allocationStatus { get; set; }
public string owner { get; set; }
public DateTime allocationDate { get; set; }
public string serviceStatus { get; set; }
public string serviceResolution { get; set; }
public FixedAssets()
{
this.category = new HashSet<Category>();
}
}
FixedAssetsView
public class FixedAssetsView
{
public int ID { get; set; }
public string name { get; set; }
public virtual ICollection<CategoryView> category { get; set; }
public string serialNo { get; set; }
public string provider { get; set; }
public DateTime acquisitionDate { get; set; }
public DateTime warrantyEnd { get; set; }
public int inventoryNo { get; set; }
public string allocationStatus { get; set; }
public string owner { get; set; }
public DateTime allocationDate { get; set; }
public string serviceStatus { get; set; }
public string serviceResolution { get; set; }
}
Category
public class Category : IEntityBase
{
public int ID { get; set; }
public string categoryName { get; set; }
public virtual ICollection<FixedAssets> fixedasset { get; set; }
public Category()
{
this.fixedasset = new HashSet<FixedAssets>();
}
}
CategoryView
public class CategoryView
{
public int ID { get; set; }
public string categoryName { get; set; }
public virtual ICollection<FixedAssetsView> fixedasset { get; set; }
}
Automapper configuration
Mapper.Initialize(x =>
{
x.CreateMap<FixedAssets, FixedAssetsView>();
x.CreateMap<FixedAssetsView, FixedAssets>();
x.CreateMap<Category, CategoryView>();
x.CreateMap<CategoryView, Category>();
});
I believe you need a .ForMember in your Mapper initialization.
eg:
Mapper.CreateMap<IEnumerable<Source>, IEnumerable<Target>>()
.ForMember(f => f, mp => mp.MapFrom(
mfrom => mfrom.Select(s => AutoMapper.Mapper.Map(s, new Target())
)
);
Am trying to map nested collections using automapper and I have done the basic setup and configuration. When I try to do the map it the nested values are coming as null. I have tried to follow few posts and put together something. I want the list to have a hierarchy instead of flattening. Any help around this would be great.
Source Entities:
public class OuterEntity
{
public int ID { get; set; }
public string Name { get; set; }
public List<InnerEntity> InnerEntityList { get; set; }
}
public class InnerEntity
{
public int InnerId { get; set; }
public string InnerName { get; set; }
public List<InnerMostEntity> InnerMostList { get; set; }
}
public class InnerMostEntity
{
public int InnerMostId { get; set; }
public string InnerMostName { get; set; }
public DateTime ModifiedDate { get; set; }
}
Destination Entities:
public class OuterEntityDTO
{
public int ID { get; set; }
public string Name { get; set; }
public List<InnerEntity> InnerEntityList { get; set; }
}
public class InnerEntityDTO
{
public int InnerId { get; set; }
public string InnerName { get; set; }
public List<InnerMostEntity> InnerMostList { get; set; }
}
public class InnerMostEntityDTO
{
public int InnerMostId { get; set; }
public string InnerMostName { get; set; }
public DateTime ModifiedDate { get; set; }
}
Controller Class:
public List<OuterEntityDTO> GetAll()
{
var outerEntityList = myRepo.GetAll(); //Type of List<OuterEntity>
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<OuterEntity, OuterEntityDTO>().ReverseMap();
cfg.CreateMap<InnerEntity, InnerEntityDTO>().ReverseMap();
cfg.CreateMap<InnerMostEntity, InnerMostEntityDTO>().ReveseMap();
});
config.AssertConfigurationIsValid();
var innerMostDTO = Mapper.Map<List<OuterEntity>,List<OuterEntityDTO>>(outerEntityList);
//The inner list at first level itself is null.
return innerMostDTO;
}
Am trying to achieve this in DOT NET Core. Autommaper version is 6.1.1
I think you should have a wrong class hierarchy in DTO classes, as you have
public List<InnerMostEntity> InnerMostList { get; set; }
in public class InnerEntityDTO, you should write it as
public List<InnerMostEntityDTO> InnerMostList { get; set; }