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?
Related
I'd like to display the 'ApplicationRole' Name with the 'ApplicationUser' data together using Eager loading.
here is my ApplicationUser
public class ApplicationUser : IdentityUser
{
public string? Name { get; set; }
public string? Department { get; set; }
public bool IsDeleted { get; set; }
public string RoleId { get; set; }
public virtual ApplicationRole Role { get; set; } = new ApplicationRole();
}
public class ApplicationUserDTO
{
public string Id { get; set; }
public int UserId { get; set; }
public string Name { get; set; }
public string UserName { get; set; }
// Foreign Key
public string RoleId { get; set; }
public virtual ApplicationRoleDTO Role { get; set; } = new ApplicationRoleDTO();
}
here is ApplicationRole
[NotMapped]
public class ApplicationRole : IdentityRole
{
public string Id { get; set; }
public string Name { get; set; }
//[InverseProperty(nameof(ApplicationUser.Role))]
public virtual ICollection<ApplicationUser> Users { get; set; } = new List<ApplicationUser>();
}
public class ApplicationRoleDTO
{
public string Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ApplicationUserDTO> Users { get; set; } = new List<ApplicationUserDTO>();
}
and here is the UserRepository
public async Task<IEnumerable<ApplicationUser>> GetAllUsersAsync()
{
//return await _dbContext.User.Where(u => u.IsDeleted == false).ToListAsync();
return await _dbContext.User.Include(u => u.Role).Where(u => u.IsDeleted == false).ToListAsync();
}
public async Task<ApplicationUser> GetUserAsync(string id)
{
return await _dbContext.User.Where(u => u.Id == id).Where(u => u.IsDeleted == false).FirstOrDefaultAsync();
}
But when I use the 'Include' keyword it show this error
When I try to use the string "Role", it also show error
public async Task<IEnumerable<ApplicationUser>> GetAllUsersAsync()
{
return await _dbContext.User.Include("Role").Where(u => u.IsDeleted == false).ToListAsync();
}
Here is the error show
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);
}
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();
I have a GenericRepository,Which CourseRepository inherits from it, and Entities returns a list of courses
public class CourseRepository : GenericRepositories<Course>, ICourseRepository
{
public CourseRepository(LearningSiteDbContext Context) : base(Context)
{
}
}
public class GenericRepositories<TEntity> : IGenericRepositories<TEntity> where TEntity : class, IEntity,new()
{
protected readonly LearningSiteDbContext context;
public DbSet<TEntity> Entities { get; set; }
public GenericRepositories(LearningSiteDbContext Context)
{
context = Context;
Entities = context.Set<TEntity>();
}
}
But When I run this handler In Razor Page
public async Task OnGetAsync(int Id, CancellationToken cancellationToken)
{
var selectedCourse = await courseRepository.Entities.FindAsync(Id,cancellationToken);
Model = mapper.Map<CourseEditVm>(selectedCourse);
}
I get the following error :
Entity type 'Course' is defined with a single key property, but 2 values were passed to the 'DbSet.Find' method
And this is Course entity class
public class Course
{
public Course()
{
}
public Course(DateTime CreateDate)
{
this.CreateDate = CreateDate;
}
public int Id {get;set;}
public string CourseTitle { get; set; }
public string CourseDescription { get; set; }
public decimal CoursePrice { get; set; }
public string ImageName { get; set; }
public string DemoFileName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime? UpdateDate { get; set; }
public bool IsDeleted { get; set; }
//Foreign key
public int? CourseStatusId { get; set; }
public int? CourseLevelId { get; set; }
public Guid? CustomUserId { get; set; }
public int? CourseGroupId { get; set; }
//Navigations
public CourseStatus CourseStatus { get; set; }
public CourseLevel CourseLevel { get; set; }
public CustomUser CustomUser { get; set; }
public CourseGroup CourseGroup { get; set; }
public ICollection<CourseEpisod> CourseEpisods { get; set; }
public ICollection<Keyword> Keywordkeys { get; set; }
}
And it's Course Config
class CourseConfig : IEntityTypeConfiguration<Course>
{
public void Configure(EntityTypeBuilder<Course> builder)
{
builder.HasKey(c => c.Id);
builder.Property(c => c.Id).ValueGeneratedOnAdd();
builder.Property(c => c.CourseTitle).HasMaxLength(50);
builder.Property(c => c.CourseDescription).HasMaxLength(400);
builder.Property(c => c.ImageName).HasMaxLength(255);
builder.Property(c => c.DemoFileName).HasMaxLength(255);
//Relations
builder.HasMany(c => c.Keywordkeys).WithOne(c => c.Course).HasForeignKey(c => c.CourseId);
builder.HasOne(c => c.CustomUser).WithMany(c => c.Courses).HasForeignKey(c => c.CustomUserId);
}
}
But when I run this code, I will no longer receive this error
var selectedCourse = await courseRepository.Entities.FirstOrDefaultAsync(c => c.Id == Id, cancellationToken);
What is the cause of this error? Is my code wrong? How should I fix this error?
You are using the wrong method, if you check here
FindAsync you can see that if you want to pass a cancellation token, you need to pass your keys as an array like this
.FindAsync(new object[]{id}, cancellationToken);
SOLUTION:
ParticipantsWithData = await _context.Participants.Select(p => new ParticipantWithData {
Participant = p,
Team = p.Teams,
FirstWeight = p.ParticipantData.Where(pd => pd.ParticipantId == p.Id).OrderBy(x => x.Date).FirstOrDefault(),
LastWeight = p.ParticipantData.Where(pd => pd.ParticipantId == p.Id).OrderByDescending(x => x.Date).FirstOrDefault()
}).ToListAsync();
And then the model:
public class ParticipantWithData {
public Participant Participant { get; set; }
public Team Team { get; set; }
public ParticipantData FirstWeight { get; set; }
public ParticipantData LastWeight { get; set; }
}
That way I can do x.FirstWeight.Date or x.FirstWeight.Weight when looping through Participants (see the ParticipantData model below),
QUESTION:
How can I use this in my view?
var query = await _context.Participants.Select(p => new {
Participant = p,
Team = p.Teams,
FirstWeight = p.ParticipantData.OrderBy(x => x.Date).FirstOrDefault(),
LastWeight = p.ParticipantData.OrderByDescending(x => x.Date).FirstOrDefault()
}).ToListAsync();
If possible, I'd like to make it a strongly typed model, but I don't know how to do that. All I've tried so far doesn't work.
The Participant model:
public class Participant {
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Guid TeamId { get; set; }
[ForeignKey("TeamId")]
public Team Teams { get; set; }
public IList<ParticipantData> ParticipantData { get; set; }
}
The ParticipantData model:
public class ParticipantData {
public Guid Id { get; set; }
public double? Weight { get; set; }
public DateTime Date { get; set; }
public Guid ParticipantId { get; set; }
public Participant Participants { get; set; }
}
The new model I'm working on:
public class ParticipantWithData {
public Participant Participant { get; set; }
public Team Team { get; set; }
public ParticipantData ParticipantData { get; set; }
public double? FirstWeight { get; set; }
public double? LastWeight { get; set; }
}
Maybe I'm way off..?
Write your ParticipantViewModel as follows:
public class ParticipantViewModel
{
public Participant Participant { get; set; }
public Team Team { get; set; }
public double? FirstWeight { get; set; }
public double? LastWeight { get; set; }
}
Then in the query:
var query = await _context.Participants.Inculde(p => p.Teams)
.Include(p => p.ParticipantData).Select(p => new ParticipantViewModel
{
Participant = p,
Team = p.Teams,
FirstWeight = p.ParticipantData.Select(pd => pd.Weight).OrderBy(x => x.Date).FirstOrDefault(),
LastWeight = p.ParticipantData.Select(pd => pd.Weight).OrderByDescending(x => x.Date).FirstOrDefault()
}).ToListAsync();
Note: I didn't see your ParticipantData model but I have answered with assumption so there may be some changes according to your actual data and requirement.