I want to sort by Module Code. I tried adding OrderBy(m => m.code) but the error says 'does not contain a definition for 'OrderBy'...'.
public async Task<IEnumerable<Module>> GetAllModules()
{
return await context.Modules
.Include(m => m.Lecturers)
.ThenInclude(ml => ml.Lecturer)
.ToListAsync();
}
Module class:
public class Module
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public ICollection<ModuleLecturer> Lecturers { get; set; }
public Module()
{
Lecturers = new Collection<ModuleLecturer>();
}
}
ModuleLecturer class:
public class ModuleLecturer
{
public int ModuleId { get; set; }
public int LecturerId { get; set; }
public Module Module { get; set; }
public Lecturer Lecturer { get; set; }
}
Lecturer class:
public class Lecturer
{
public int Id { get; set; }
public string Name { get; set; }
public string Title { get; set; }
}
Related
Currently I'm creating a new feature. It looks simple, but I am stuck at a problem with automapping dto to another one.
I have to create a wishlist [adding /deleting items of wishlist].
All works fine, except one thing: while adding an item to the wishlist, I'm get a message like this:
"type": "AutoMapperMappingException",
"message": "Error mapping types..."
However, I can see it got inserted into the database. Also, can delete it too. I understand the problem is linked to Automapper, but I could not figure out how to map correctly.
[HttpPost]
public async Task<IActionResult> Add(WishListItemCreationDto wishListItemDto)
{
var itemAdd = _mapper.Map<WishlistItemDto>(wishListItemDto);
var itemCreated = await _wishListItemService.AddAsync(itemAdd);
return CreatedAtAction(nameof(GetId), new { id = itemCreated.Id }, wishListItemDto);
}
//service
public async Task<WishlistItemDto> AddAsync(WishlistItemDto item)
{
var entity = _mapper.Map<WishlistItem>(item);
var entityDetails = await _productDetailsRepository.GetById(item.ProductDetailId);
entity.ProductDetails = entityDetails;
await _wishListItemRepository.AddAsync(entity);
return _mapper.Map<WishlistItemDto>(entity);
}
DTOs:
public class WishListItemCreationDto
{
[Required]
public string CustomerId { get; set; }
[Required]
public int ProductDetailId { get; set; }
[Min(1)]
[Required]
public int Quantity { get; set; }
}
public class WishlistItemDto
{
public int Id { get; set; }
public string CustomerId { get; set; }
public int ProductDetailId { get; set; }
public ProductDetailsDtoWithPrimaryImage ProductDetails { get; set; }
public int Quantity { get; set; }
}
public class WishlistItem
{
public int Id { get; set; }
public string CustomerId { get; set; }
public Customer Customer { get; set; }
public int ProductDetailsId { get; set; }
public ProductDetails ProductDetails { get; set; }
public int Quantity { get; set; }
}
ProductDetails DTO:
public class ProductDetails
{
public int Id { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
public IList<ProductAttributeValue> ProductAttributes { get; set; } = new List<ProductAttributeValue>();
public int Quantity { get; set; }
public string Sku => $"BRD{Id}";
public byte[] RowVersion { get; set; } = new byte[0];
}
public class ProductDetailsDtoWithPrimaryImage
{
public int Id { get; set; }
public int Quantity { get; set; }
public int ProductId { get; set; }
public ProductDisplayEntity Product { get; set; }
public IEnumerable<ProductAttributeWithValueDto> ProductAttributes { get; set; }
public byte[] RowVersion { get; set; }
public string Sku => $"BRD{Id}";
public int? PrimaryImageId { get; set; }
}
AutoMapper:
public WishlistItemProfile()
{
CreateMap<WishlistItem, WishListItemCreationDto>().ReverseMap();
CreateMap<WishlistItemDto, WishListItemCreationDto>().ReverseMap();
CreateMap<WishlistItem, WishlistItemDto>()
.ForMember(wi => wi.ProductDetailId, opt => opt.MapFrom(f => f.ProductDetailsId))
.ForMember(wi => wi.ProductDetails, opt => opt.MapFrom(f => f.ProductDetails))
.ReverseMap();
}
everything is okay, but you missed inner mapping of your classes.
What the error says:
Mapping types:
ProductDetailsDtoWithPrimaryImage -> ProductDetails
SimpleWebApi.Controllers.ProductDetailsDtoWithPrimaryImage -> SimpleWebApi.Controllers.ProductDetails
Add additional mapping in your constructor WishlistItemProfile
CreateMap<ProductDetails, ProductDetailsDtoWithPrimaryImage>().ReverseMap();
And it starts works perfect
I am trying to find a simple way using AutoMapper to return all companies that are linked to a specific User Id in a many-to-many relationship scenario. I followed the SO Automapper many to many mapping but I get the error message "Expression of type 'System.Collections.Generic.List`1[API.Entities.CompanySetting]' cannot be used for parameter of type 'System.Linq.IQueryable" when trying to follow the logic.
My AppUser entity:
public class AppUser
{
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<AppUserCompanySetting> AppUserCompanySettings { get; set; } = new List<AppUserCompanySetting>();
}
My CompanySetting entity:
public class CompanySetting
{
public int Id { get; set; }
public string CompanyName { get; set; }
public string CompanyRegistrationNumber { get; set; }
public bool isActive { get; set; }
public bool isArchived { get; set; }
public virtual ICollection<AppUserCompanySetting> AppUserCompanySettings { get; set; } = new List<AppUserCompanySetting>();
}
And I have the Join table
public class AppUserCompanySetting
{
public int AppUserId { get; set; }
public virtual AppUser AppUser { get; set; }
public int CompanySettingsId { get; set; }
public virtual CompanySetting CompanySettings { get; set; }
}
I then created a CompanySettingDto
public class CompanySettingDto
{
public int Id { get; set; }
public string CompanyName { get; set; }
public string CompanyRegistrationNumber { get; set; }
public bool isActive { get; set; }
public bool isArchived { get; set; }
}
And a MemberDto:
public class MemberDto
{
public int Id { get; set; }
public string Username { get; set; }
public string PhotoUrl { get; set; }
public string KnownAs { get; set; }
public int TimeActive { get; set; }
public DateTime LastActive {get; set;}
public ICollection<PhotoDto> Photos { get; set; }
public ICollection<CompanySettingDto> CompanyInformation { get; set; }
}
I then tried Automapper to bring the relationships between the User and the Company Information I require:
public class AutoMapperProfiles : Profile
{
public AutoMapperProfiles()
{
CreateMap<AppUser, MemberDto>()
.ForMember(dest => dest.CompanyInformation, opt => opt.MapFrom(x => x.AppUserCompanySettings.Select(y => y.CompanySettings).ToList()))
CreateMap<CompanySetting, CompanySettingDto>();
}
}
I am writing an API call to get all companies that are linked to a specific UserId.
public async Task<IEnumerable<MemberDto>> GetCompaniesByUserIdAsync(int userId)
{
return await _context.Users
.Where(x => x.Id == userId)
.ProjectTo<MemberDto>(_mapper.ConfigurationProvider)
.ToListAsync();
}
Goal: Create a one-to-one relationship between EF Asp.Net.Identity.User and EF UserBusiness
This is my EF Asp.Net.Identity.User:
public class UserEntity:IdentityUser
{
public override string Id { get; set; }
public override string UserName { get; set; }
public override string Email { get; set; }
public override string NormalizedUserName { get; set; }
public override string NormalizedEmail { get; set; }
public string Telephone { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
public DateTime? DateOfBirth { get; set; }
public string NIF { get; set; }
public string Gender { get; set; }
public string Password { get; set; }
public bool IsUserProfileCompleted { get; set; }
**public ICollection<UserBusinessEntity> Business { get; set; }**
public ICollection<PatientEntity> Patients { get; set; }
public DateTime UpdatedOn { get; set; }
public bool IsDeleted { get; set; }
public DateTime CreatedOn { get; set; }
My EF UserBusiness:
[Table ("UserBusiness")]
public class UserBusinessEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string BusinessId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
public string Telephone { get; set; }
public string Email { get; set; }
public string Fax { get; set; }
public string Owner { get; set; }
public string OwnerPointofContact { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime DeletedOn { get; set; }
public DateTime UpdatedOn { get; set; }
[ForeignKey("Id")]
public string Id { get; set; }
public virtual UserEntity User { get; set; }
}
Repository:
==> RepositoryExtension:
public static IQueryable<UserEntity> BuildUserWithBusiness(this IQueryable<UserEntity> query)
{
return query.Include(u => u.Business);
}
==> Repository
public async Task<UserEntity> GetByIdWithBusinessAsync(string businessId)
{
return await _context.Users
.BuildUserWithBusiness()
.FirstOrDefaultAsync(x => x.Id == businessId);
}
Fluent API:
public class DentalClinicDbContext : IdentityDbContext<UserEntity, UserRoleEntity, string>
{
public DbSet<UserBusinessEntity> UserBusiness { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<UserEntity>(entity =>
{
entity.ToTable("Users");
});
builder.Entity<UserEntity>(entity =>
{
entity.HasOne(b => b.Business)
.WithOne(u => u.User);
});
I got an error on u.User
Error:
'ICollection' does not contain a definition for 'User' and no accessible extension method 'User' accepting a first argument of type 'Collection could be found (are you missing a using directive or an assembly reference?)
There is a line in your code,
public ICollection<UserBusinessEntity> Business { get; set; }
which should be changed to,
public UserBusinessEntity Business { get; set; }
Also, the model builder should be changed to,
builder.Entity<UserEntity>(entity =>
{
entity.HasOne(b => b.Business)
.WithOne(u => u.User);
.HasForeignKey<BusinessUser>(c => c.Id);
});
Please note that I haven't tried the code real-time.
You should follow this example:
https://www.entityframeworktutorial.net/efcore/configure-one-to-one-relationship-using-fluent-api-in-ef-core.aspx
Why is there a UserProgramRefProgramCharacteristics.RefProgramCharacteristicsId field??? There should only be 2 fields not 3. Right? Below are the 3 classes and the OnModelCreating that is needed to create a many to many table
public class RefProgramCharacteristic
{
public int Id { get; set; }
public string ProgramCharacteristic { get; set; }
public List<UserProgramRefProgramCharacteristic> UserProgramRefProgramCharacteristics { get; set; }
// public ICollection<UserProgram> userPrograms { get; } = new List<UserProgram>();
// public virtual ICollection<UserProgram> UserPrograms { get; set; }
}
public class UserProgram
{
public int Id { get; set; }
//UserProgramSaved
public bool MyList { get; set; }
public float MyPriorityRating { get; set; }
public int Similarity { get; set; }
public bool Compare { get; set; }
//UserProgramSimilarity
public int OverallSimilarityScore { get; set; }
public int DeltaProfileElement1_WorkExp { get; set; }
public int DeltaProfileElement2_VolExp { get; set; }
public int DeltaProfileElement3_ResExp { get; set; }
public int DeltaProfileElement4_Pubs { get; set; }
public int DeltaProfileElement5_Step1 { get; set; }
public int DeltaProfileElement6_Step2ck { get; set; }
public int DeltaProfileElement7_Aoa { get; set; }
public int DeltaProfileElement8_Nspecialties { get; set; }
public int DeltaProfileElement9_PercentApps { get; set; }
//UserComparisonSaved
// public RefProgramCharacteristic RefProgramCharacteristic { get; set; }
public string RefProgramCharacteristicList { get; set; }
public string ApplicationUserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public int MedicalProgramId { get; set; }
public RefProgramDetailData MedicalProgram { get; set; }
public List<UserProgramRefProgramCharacteristic> UserProgramRefProgramCharacteristics { get; set; }
// public ICollection<RefProgramCharacteristic> RefProgramCharacteristics { get; } = new List<RefProgramCharacteristic>();
// public virtual ICollection<RefProgramCharacteristic> RefProgramCharacteristics { get; set; }
}
public class UserProgramRefProgramCharacteristic
{
// public int Id { get; set; }
public int UserProgramId { get; set; }
public UserProgram UserProgram { get; set; }
public int RefProgramCharacteristicsId { get; set; }
public RefProgramCharacteristic RefProgramCharacteristic { get; set; }
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<UserProgramRefProgramCharacteristic>()
.HasKey(t => new { t.UserProgramId, t.RefProgramCharacteristicsId });
base.OnModelCreating(builder);
}
Why is there a UserProgramRefProgramCharacteristics.RefProgramCharacteristicsId field?
Because you are telling EF Core to create such field here:
public int RefProgramCharacteristicsId { get; set; }
// ^
While the navigation property is called RefProgramCharacteristic (no s). And by EF Core conventions:
If the dependent entity contains a property named <primary key property name>, <navigation property name><primary key property name>, or <principal entity name><primary key property name> then it will be configured as the foreign key.
RefProgramCharacteristicsId does not match any of these rules, so EF Core creates a shadow FK property with default name RefProgramCharacteristicId.
Either rename the property to RefProgramCharacteristicId (best), or map it explicitly using ForeignKey data annotation:
[ForeignKey(nameof(RefProgramCharacteristicsId))]
public RefProgramCharacteristic RefProgramCharacteristic { get; set; }
or
[ForeignKey(nameof(RefProgramCharacteristic))]
public int RefProgramCharacteristicsId { get; set; }
or using HasForeignKey fluent API:
builder.Entity<UserProgramRefProgramCharacteristic>()
.HasOne(e => e.RefProgramCharacteristic)
.WithMany(e => e.UserProgramRefProgramCharacteristics)
.HasForeignKey(e => e.RefProgramCharacteristicsId);
public class CreateProjeModel
{
public Proje Proje { get; set; }
public List<GeometryModel> GeometryList { get; set; }
public CreateProjeModel()
{
Proje = new Proje();
GeometryList = new List<GeometryModel>();
}
}
public class GeometryModel
{
public List<PointModel> PointList { get; set; }
public GeometryModel()
{
PointList = new List<PointModel>();
}
}
public class PointModel
{
public int X { get; set; }
public int Y { get; set; }
}
public class Proje : EntityBase
{
public int FirmaId { get; set; }
public int IlId { get; set; }
public int? IlceId { get; set; }
public int PlanTurId { get; set; }
public int EtudTurId { get; set; }
public int EtudAmacId { get; set; }
public int DilimId { get; set; }
public string Aciklama { get; set; }
public virtual Firma Firma { get; set; }
public virtual IL Il { get; set; }
public virtual ILCE Ilce { get; set; }
public virtual PlanTur PlanTur { get; set; }
public virtual EtudTur EtudTur { get; set; }
public virtual EtudAmac EtudAmac { get; set; }
public virtual Dilim Dilim { get; set; }
}
I have a complex model named CreateProjeModel. I'm using 'for' to loop collection properties and binding like below:
#Html.TextBoxFor(m => m.GeometryList[i].PointList[j].X)
Action is like below:
[HttpPost]
public async Task<ActionResult> Create(CreateProjeModel proje)
{
//ToDo
return View(proje);
}
Posted data is below:
When it comes to action, GeometryList is empty and Proje's properties are not set to post values. Where am I doing wrong?
Your problem is that your CreateProjeModel model has a property named Proje, but the parameter of your Create() method is also named proje. Your need to change the method signature to (say)
public async Task<ActionResult> Create(CreateProjeModel model)
where the parameter name is not the same as the nae of one of your properties