How can I Get the results of the nested query in the form of entities with EF - asp.net-core

I have some models in my project:
**Model ServiceDeliveryDoc**
public string Id { get; set; }
public string PartnerDocId { get; set; }
public DateTime Date { get; set; }
public decimal Cost { get; set; }
public string LegalEntityId { get; set; }
[ForeignKey("LegalEntityId")]
[InverseProperty("ServiceDeliveryDoc")]
public LegalEntity LegalEntity { get; set; }
[InverseProperty("ServiceDeliveryDoc")]
public ICollection<ServiceRegistryToServiceDeliveryDoc> ServiceRegistryToServiceDeliveryDoc { get; set; }
**Model ServiceRegistry**
public string Id { get; set; }
public DateTimeOffset Date { get; set; }
public decimal Cost { get; set; }
[InverseProperty("ServiceRegistry")]
public ICollection<ServiceRegistryToServiceDeliveryDoc> ServiceRegistryToServiceDeliveryDoc { get; set; }
**Model ServiceRegistryToServiceDeliveryDoc**
public string Id { get; set; }
public string ServiceRegistryId { get; set; }
public string ServiceDeliveryDocId { get; set; }
[ForeignKey("ServiceDeliveryDocId")]
[InverseProperty("ServiceRegistryToServiceDeliveryDoc")]
public ServiceDeliveryDoc ServiceDeliveryDoc { get; set; }
[ForeignKey("ServiceRegistryId")]
[InverseProperty("ServiceRegistryToServiceDeliveryDoc")]
public ServiceRegistry ServiceRegistry { get; set; }
I write some nested query in SQL to get ServiceDeliveryDoc with
LegalEntity, filtered by ServiceRegistryId:
SELECT ReturnsTable.[Id]
,ReturnsTable.[PartnerDocId]
,ReturnsTable.[Date]
,ReturnsTable.[Cost]
,ReturnsTable.[LegalEntityId]
,LegalEntityTable.[Name]
,ReturnsTable.[DocProcessId]
FROM [Vishnya].[dbo].[ServiceDeliveryDoc] as ReturnsTable
left join [Vishnya].[dbo].[LegalEntity] as LegalEntityTable
on ReturnsTable.[LegalEntityId] = LegalEntityTable.[Id]
where ReturnsTable.Id in ( select ServiceDeliveryDocId
from ServiceRegistry_To_ServiceDeliveryDoc
where ServiceRegistryId = #ServiceRegistryId)
How I can recieve simular result, using Enity framework?

From your SQL query and the model design , there is a one-to-one relationship between ServiceDeliveryDoc and LegalEntity , many-to-many relationship between ServiceDeliveryDoc and ServiceRegistry . For loading related data , you could use include like below:
var result = _context.ServiceDeliveryDoc
.Include(sd => sd.LegalEntity)
.Where(sd =>
_context.ServiceRegistryToServiceDeliveryDoc
.Where(srt => srt.ServiceRegistryId == "101")
.Select(srt => srt.ServiceDeliveryDocId)
.Contains(sd.Id)
)
.Select(sd => new
{
sd.Id,sd.PartnerDocId , sd.Date,sd.Cost,sd.LegalEntityId, sd.LegalEntity.Name
}).ToList();
DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ServiceRegistryToServiceDeliveryDoc>()
.HasOne(sr => sr.ServiceDeliveryDoc)
.WithMany(sd => sd.ServiceRegistryToServiceDeliveryDoc)
.HasForeignKey(sr => sr.ServiceDeliveryDocId);
modelBuilder.Entity<ServiceRegistryToServiceDeliveryDoc>()
.HasOne(sr => sr.ServiceRegistry)
.WithMany(sd => sd.ServiceRegistryToServiceDeliveryDoc)
.HasForeignKey(sr => sr.ServiceRegistryId);
}

Related

Entity Framework: get data from many-to-many relationship

I work on an API and when I want to get data from a many-to-many relationship, I get back null.
The connection with the database is OK, and Post date work.
But when I get info from the database, the table for the many-to-many relationship is empty
public class User
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(30)]
public string Pseudo { get; set; }
[EmailAddress]
public string Mail { get; set; }
[Required]
public string Pwd { get; set; }
[Required]
public bool IsAdmin { get; set; }
public ICollection<Project> UsersProjectstry { get; set; }
public ICollection<UserProjectMTM> UsersProjects { get; set; }
}
public class Project
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(30)]
public string Name { get; set; }
[Required]
[MinLength(100)]
public string Description { get; set; }
public string? img { get; set; }
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; }
[Required]
public int SumGoal { get; set; }
public int Sum { get; set; }
[Required]
public User ProjectManager { get; set; }
public ICollection<UserProjectMTM> Donator { get; set; }
}
public class UserProjectMTM
{
public int PId { get; set; }
public Project Project { get; set; }
public int UId { get; set; }
public User User { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new ProjectConfig());
modelBuilder.ApplyConfiguration(new UserConfig());
modelBuilder.ApplyConfiguration(new CommentConfig());
modelBuilder.Entity<UserProjectMTM>().HasKey(x => new { x.UId, x.PId });
modelBuilder.Entity<UserProjectMTM>().HasOne(p=> p.Project).WithMany(u=> u.Donator).HasForeignKey(x=>x.PId);
modelBuilder.Entity<UserProjectMTM>().HasOne(u => u.User).WithMany(p=> p.UsersProjects).HasForeignKey(x => x.UId);
}
public IEnumerable<TEntity> GetAll()
{
return _Context.Set<TEntity>();
}
public TEntity? GetById(params object[] Id)
{
return _Context.Set<TEntity>().Find(Id);
}
I try a lot of things - so far without success.
I'm junior and I can't find the solution - please help.

Convert SQL query to Entity Framework which used AggregateFunctions and Where clause

How can I convert this query to Entity Framework?
SQL query:
SELECT Fullname, SUM(CoinCount+DiamondCount) AS GeneralPoint
FROM Students, Groups
WHERE Students.GroupId = Groups.Id AND Groups.Name = 'FSDA_1813_az'
GROUP BY Fullname
ORDER BY GeneralPoint
Entity:
public class Student
{
public int Id { get; set; }
public int GroupId { get; set; }
public string Fullname { get; set; }
public Nullable<int> DiamondCount { get; set; }
public Nullable<int> CoinCount { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public string Education { get; set; }
public string Email { get; set; }
public System.DateTime Birthdate { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public Nullable<System.DateTime> LastVisited { get; set; }
public string Facebook { get; set; }
public string Linkedin { get; set; }
public string SocialMedia { get; set; }
public byte[] Photo { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Comment> Comments { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Exam> Exams { get; set; }
public virtual Group Group { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Point> Points { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<StudentHomework> StudentHomeworks { get; set; }
}
UserRepository:
public ICollection<Student> GetUsersForGroup(string group)
{
using (var db = new EFContext())
{
var temp = db.Students.Where(x => x.Group.Name == group).ToList();
// I have to sort students in group by their DiamondCount+CoinCount as new GeneralCount
temp = temp.OrderBy(x => );
}
}
I have to sort students for their general point (DiamondCount+CoinCount).
But I can't send LINQ query by using Entity Framework. How can I do this?
Not tested but it should work:
var result = db.Students.Where(x => x.Group.Name == group)
.GroupBy(g => g.Fullname)
.Select(i => new
{
FullName = i.Key,
GeneralPoint = i.Sum(s => s.DiamondCount + s.CoinCount)
})
.OrderBy(o => o.GeneralPoint)
.ToList();

Missing type map configuration or unsupported mapping.for Collection of DTO

I was making an API for saving a model where it has one to many relationship with another model. When I applying automapping in it. it is giving me following error:
CreateContestDto -> Contest
tritronAPI.DTOs.CreateContestDto -> tritronAPI.Model.Contest
Type Map configuration:
CreateContestDto -> Contest
tritronAPI.DTOs.CreateContestDto -> tritronAPI.Model.Contest
Destination Member:
Problems
---> AutoMapper.AutoMapperMappingException: Missing type map
configuration or unsupported mapping.
Mapping types:
ProblemDto -> Problem
tritronAPI.DTOs.ProblemDto -> tritronAPI.Model.Problem
at lambda_method(Closure , ProblemDto , Problem , ResolutionContext )
My models are: Contest and Problem a contest contain many problems:
public class Contest
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public ICollection<Problem> Problems { get; set; }
public ICollection<ContestProgrammingLanguage>
ContestProgrammingLanguages { get; set; }
}
public class Problem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(255)]
public string ProblemName { get; set; }
[ForeignKey("User")]
public string ProblemAuthorId { get; set; }
public virtual User ProblemAuthor { get; set; }
public string AuthorName { get; set; }
//public virtual List<Resources> Resourceses { get; set; }
public string ProblemDescription { get; set; }
public bool IsPublished { get; set; }
public virtual ICollection<Submission> Submissions { get; set; }
public string Tags { get; set; }
//public Guid Contest_Id { get; set; }
public virtual Contest Contest { get; set; }
[ForeignKey("Contest")]
public int? Contest_Id { get; set; }
public short Score { get; set; }
//Timelimit in miliseconds
public int TimeLimit { get; set; }
//MemoryLimit in bytes
public int MemoryLimit { get; set; }
//More than source code limit is not allowed
public int? SourceCodeLimit { get; set; }
public virtual ICollection<TestFile> TestFiles { get; set; } = new
List<TestFile>();
}
public class CreateContestDto
{
public CreateContestDto()
{
this.Problems = new HashSet<ProblemDto>();
}
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndDate { get; set; }
public DateTime EndTime { get; set; }
public string BackgroundImage { get; set; }
public string Description { get; set; }
public ICollection<ProblemDto> Problems { get; set; }
}
public class ProblemDto
{
public int Id { get; set; }
public string ProblemName { get; set; }
}
mapping profile:
CreateMap<CreateContestDto, Contest>().ForMember(
dest => dest.Problems , opt => opt.MapFrom(src =>
src.Problems));
controller code:
public async Task<IActionResult> AddContest([FromBody]
CreateContestDto contest)
{
var con = _mapper.Map<Contest>(contest);
this._uow.ContestRepository.Add(con);
return Ok();
}
I have already tried with reversemap selecting new id in mapping profile
You also need to add mappings for ProblemDTO to Problem:
CreateMap<CreateContestDto, Contest>();
CreateMap<ProblemDto, Problem>();

Relations with DbQuery

I have this Participant model DbSet<Participants>:
public class Participant {
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int IsCaptain { get; set; }
public Guid TeamId { get; set; }
[ForeignKey("TeamId")]
public Team Team { get; set; }
}
And this ParticipantDataView DbQuery<ParticipantsDataView>:
public class ParticipantDataView {
public Guid Id { get; set; } // = Participant.Id
public double? FirstWeight { get; set; }
public double? LastWeight { get; set; }
public double? WeightLoss => FirstWeight - LastWeight;
public Participant Participant { get; set; }
}
DbContext:
public class DBContext : DbContext {
public DBContext(DbContextOptions<DBContext> options) : base(options) {}
public DbSet<Participant> Participants { get; set; }
public DbQuery<ParticipantDataView> ParticipantsDataView { get; set; }
}
My query:
Participants = await _context.ParticipantsDataView
.Include(p => p.Participant)
.ThenInclude(t => t.Team)
.Where(p => p.Participant.Status == 1 && p.Participant.Team.Status == 1).OrderBy(p => p.WeightLoss)
.AsNoTracking()
.ToListAsync();
The error:
SqlNullValueException: Data is Null.
This method or property cannot be called on Null values.
Every item in ParticipantDataView has a match in Participants so I don't know why I get this error?

Entity Framework Parent\Child Retrieval

I have an ID of a "Component" parent record that I need to retrieve all the "Attachment" child records. The grid I am using need fields returned an placed in "TheComponentAttachmentsJoinedTable" I am only able to retrieve one record. I have used the value of FirstorDefault. That is the only way it will accept the line of code without complaining about the IEnumerable to int. Could someone please explain what is incorrect?
public class Component
{
public int ID { get; set; }
public string ComponentCode { get; set; }
public string ComponentDescription { get; set; }
public double ComponentWeight { get; set; }
public double ComponentQuantity { get; set; }
public string LastModUser { get; set; }
public DateTime LastModDate { get; set; }
public virtual ICollection<Attachment> Attachments { get; set; }
public virtual ICollection<Product> Products { get; set; }
public virtual ICollection<Element> Elements { get; set; }
}
public class Attachment
{
public int ID { get; set; }
public string AttachmentDescription { get; set; }
public string OriginalName { get; set; }
public string MimeType { get; set; }
public byte[] bytes { get; set; }
public string LastModUser { get; set; }
public DateTime LastModDate { get; set; }
//Navigation
public virtual ICollection<Element> Elements { get; set; }
public virtual ICollection<Component> Components { get; set; } //lt M-m
}
public class TheComponentAttachmentsJoinedTable
{
public int ComponentID { get; set; }
public int AttachmentID { get; set; }
public string OriginalName { get; set; }
}
public static List<TheComponentAttachmentsJoinedTable> ComponentAttachments_GetAllByComponentID(int ComponentID)
{
using (TheContext TheDB = new TheContext())
{
var r = (from x in TheDB.Component
.Where(x => x.ID == ComponentID)
.Include(x => x.Attachments)
select new TheComponentAttachmentsJoinedTable
{
ComponentID = x.ID,
AttachmentID = x.Attachments.Select(y => (y.ID)).FirstOrDefault(),
OriginalName = x.Attachments.Select(y => y.OriginalName).FirstOrDefault().ToString(),
}
);
return r.ToList();
}