ArgumentNullException: Value cannot be null. (Parameter 'source') - sql-server

I have parent and childs nested tables.
Here is my model:
public class Categories
{
[Key]
public int CategoriesId { get; set; }
public int Order { get; set; }
public string CategoryName { get; set; }
public List<News> News { get; set; }
}
public class News
{
[Key]
public int NewsId { get; set; }
public int CategoriesId { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
...
public List<Comments> Comments { get; set; }
public Categories Categories { get; set; }
}
public class Comments
{
[Key]
public int CommentsId { get; set; }
public int NewsId { get; set; }
public string Comment { get; set; }
...
public News News { get; set; }
}
public class NewsImages
{
[Key]
public int ImageId { get; set; }
public int NewsId { get; set; }
public string ImageUrl { get; set; }
public bool Cover { get; set;}
...
public News News { get; set; }
}
I'm trying to send it from ViewComponent to View;
public async Task<IViewComponentResult> InvokeAsync()
{
var group = _dbContext.Categories.Where(k => k.Order != 0).OrderBy(h => h.Order)
.Select(c => new
{
C = c,
N = c.News.OrderByDescending(n => n.Date).Take(5)
.Select(r => new
{
Y = r.Comments,
R = r.NewsImages.Where(rs => rs.Cover == true).FirstOrDefault()
})
});
var model = group
.Select(m => m.C);
return View(await model.ToListAsync()) ;
}
I am sure there are enough News records for every Category, But I get error :
ArgumentNullException: Value cannot be null. (Parameter 'source')
AspNetCore.Views_Shared_Components_IndexKategori_Default.ExecuteAsync() in Default.cshtml
var bp = k.News.FirstOrDefault();
if I use that code works fine :
var model = _dbContext.Categories
.Include(h => h.News).ThenInclude(h => h.Comments)
.Include(h => h.News).ThenInclude(h => h.NewsImages)
.Where(h => h.Order != 0)
.OrderBy(h => h.Order)
But when I use the code above, a few records appear for some categories, and some categories react as if there are no records.
Where am I making mistakes?
Thank you in advance for those who helped ..

Whenever you have a big LINQ statement that throws an exception, and you can't find where the exception comes form, translate the LINQ into smaller steps, and ToList() every step.
public async Task<IViewComponentResult> InvokeAsync()
{
// Temp code: small steps, ToList after every step
var a = dbContext.Categories.Where(category => category.Order != 0).ToList();
var b = a.OrderBy(category => category.Order).ToList();
var c = b.Select(category => new
{
Category = category,
News = category.News.OrderByDescending(news => news.Date)
.Take(5)
.ToList();
})
.ToList();
var d = c.Select(item => new
{
Category = item.Category,
NewsItems = item.News.Select(news => new
{
Comments = news.Comments,
Images = news.NewsImages.Where(newsImage => newsImage.Cover).ToList(),
})
.ToList(),
})
.ToList();
var e = d.Select(item => new
{
Category = item.Category,
NewsItems = item.NewsItems.Select(newsItem => new
{
Comments = newsItem.Comments,
Images = images.FirstOrDefault();
})
.ToList(),
})
.ToList();
// original code:
var group = _dbContext.Categories.Where...
}
I'm sure that your debugger will tell you which step is incorrect.

Related

update and delete (single query) (EF + .NET Core Api)

what's up? I have an API made with .NET Core API + EF where I have a Many-to-Many relationship between Doctor and Specialty, from which a DoctorSpecialities table arises. That is, a doctor can have several specialties.
I use React JS and what I want to do is have in the interface, a table with the specialties of the chosen doctor and when I send the form, the data in the DoctorSpecialities table is updated or deleted.
If the user deleted or added specialties, can all that be done in a single query?
My question is how to do the controller method, with that I have problems.
Doctor
public partial class Doctor
{
public Doctor()
{
DoctorSpecialties = new HashSet<DoctorSpecialties>();
}
public int DoctorId { get; set; }
public string DoctorName { get; set; }
public string DoctorProfileImg { get; set; }
public string DoctorPhoneNumber { get; set; }
public string DoctorEmail { get; set; }
public string DoctorStatus { get; set; }
public string DoctorGender { get; set; }
public ICollection<DoctorSpecialties> DoctorSpecialties { get; set; }
}
Specialty
public partial class Specialty
{
public Specialty()
{
DoctorSpecialties = new HashSet<DoctorSpecialties>();
}
public int SpecialtyId { get; set; }
public string SpecialtyName { get; set; }
public ICollection<DoctorSpecialties> DoctorSpecialties { get; set; }
}
DoctorSpecialties
public partial class DoctorSpecialties
{
public DoctorSpecialties()
{
Appointment = new HashSet<Appointment>();
DoctorSchedule = new HashSet<DoctorSchedule>();
}
public int DoctorSpecialtiesId { get; set; }
public int? DoctorId { get; set; }
public int? SpecialtyId { get; set; }
[JsonIgnore]
public Doctor Doctor { get; set; }
public Specialty Specialty { get; set; }
public ICollection<Appointment> Appointment { get; set; }
public ICollection<DoctorSchedule> DoctorSchedule { get; set; }
}
Context
modelBuilder.Entity<DoctorSpecialties>(entity =>
{
entity.ToTable("doctor_specialties");
entity.Property(e => e.DoctorSpecialtiesId).HasColumnName("doctor_specialties_id");
entity.Property(e => e.DoctorId).HasColumnName("doctor_id");
entity.Property(e => e.SpecialtyId).HasColumnName("specialty_id");
entity.HasOne(d => d.Doctor)
.WithMany(p => p.DoctorSpecialties)
.HasForeignKey(d => d.DoctorId)
.HasConstraintName("FK__doctor_sp__docto__2A4B4B5E");
entity.HasOne(d => d.Specialty)
.WithMany(p => p.DoctorSpecialties)
.HasForeignKey(d => d.SpecialtyId)
.HasConstraintName("FK__doctor_sp__speci__29572725");
});
I tried with:
[HttpPut("test/{id}")]
public async Task<IActionResult> Edit(int id, Doctor doctor)
{
if (id != doctor.DoctorId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
Doctor plantToBeUpdated = await _context.Doctor.Include(p => p.DoctorSpecialties).FirstOrDefaultAsync(p => p.DoctorId == id);
if (plantToBeUpdated != null)
{
plantToBeUpdated.DoctorSpecialties.Clear();
if (doctor.DoctorSpecialties.Count > 0)
{
foreach (var scId in doctor.DoctorSpecialties)
{
plantToBeUpdated.DoctorSpecialties.Add(new DoctorSpecialties()
{
DoctorId = plantToBeUpdated.DoctorId,
SpecialtyId = scId.SpecialtyId
});
}
}
plantToBeUpdated.DoctorName = doctor.DoctorName;
_context.Doctor.Update(plantToBeUpdated);
await _context.SaveChangesAsync();
}
}
catch (DbUpdateConcurrencyException)
{
throw;
}
}
return Ok(doctor);
}
but, doesn't work :c

Join 2 services and use on Controller on ASP.NET Core

I have a view Model:
public class CountViewModel
{
public int NewsLetterEmailCount { get; set; }
public int CurrentMonthNewsLetter { get; set; }
public int NewsLetterPercentage { get; set; }
}
then I create the second ViewModel that want to list of title:
public class AdminDashboardUnreadMessage
{
[Display(Name = "عنوان")]
public string Title { get; set; }
//public List<AdminDashboardUnreadMessage>
AdminDashboardUnreadMessages { get; set; }
}
I have a ticket Table, these are my 2 services:
public async Task<CountViewModel> AdminContentCount()
{
CountViewModel adminContetnCount = new CountViewModel()
{
UserCount = await _userRepository.UserCount(),
CurrentMonthUser = await _userRepository.CurrentMonthUser(),
NewsLetterEmailCount = await _newsLetterRepository.NewsLetterEmailCount(),
CurrentMonthNewsLetter = await _newsLetterRepository.CurrentMonthNewsLetterEmail(),
return adminContetnCount;
}
public async Task<List<AdminDashboardUnreadMessage>> ShowUnReadTicketMessages()
{
return await _userRepository.ShowUnReadTicketMessages();
}
How can I use 2 services on my service
I mean I don't want to use from View Data
I think you need to define a new ViewModel like this :
public class NewViewModel
{
public CountViewModel CountModel { get; set; }
public AdminDashboardUnreadMessage AdminDashboardModel { get; set; }
}
And now you need to return this object as a result of a newly created service which responsible to aggregate the result of two different services.
public async Task<NewViewModel> NewService()
{
var adminContetnCount = await AdminContentCount();
var dashboard = await ShowUnReadTicketMessages();
return new NewViewModel
{
CountModel = adminContetnCount,
AdminDashboardModel= dashboard
};
}

INSERT statement conflicted with foreign key constraint - SQL Server/Entity Framework Core

I get this error in my .NET Core 3.1 app:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_DiaryDiaryEntry". The conflict occurred in database "xxxxxx", table "dbo.Diaries", column 'Id'.
I can't see anything wrong with the tables themselves.
public partial class Diaries
{
public long Id { get; set; }
public string CoverImage { get; set; }
public short Year { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public long ChildId { get; set; }
public Children Child { get; set; }
public ICollection<DiaryEntries> DiaryEntries { get; set; }
}
public partial class DiaryEntries
{
public long Id { get; set; }
public DateTime Date { get; set; }
public string Content { get; set; }
public long DiaryId { get; set; }
public Diaries Diary { get; set; }
public ICollection<Images> Images { get; set; }
}
My code? Probably an entirely different matter.
This is the code that generates the error.
[HttpPost("CreateYear/{id}")]
public async Task<IActionResult> CreateYearOfEntries([FromRoute] int id)
{
// The id is the ID of an existing diary
// Make sure the diary does exist first and that it belongs to the current logged-in user
var diary = _diaryRepository.Find(id);
if (diary == null) return NotFound();
var year = diary.Result.Year;
if (await _diaryEntryRepository.OwnerIsLoggedIn(LoggedInUser.ParentId, id))
{
var noOfDays = DateTime.IsLeapYear(year) ? 366 : 365;
var i = 0;
for (; i < noOfDays; i++)
{
var date = new DateTime(year, 1, 1).AddDays(i);
var newDiaryEntry = new DiaryEntries()
{
Content = " ",
Date = date,
DiaryId = diary.Id
};
await _diaryEntryRepository.Add(newDiaryEntry);
}
return Ok();
}
return NotFound();
}
public class DiaryEntryRepository : IDiaryEntryRepository
{
private readonly ApplicationDbContext _context;
public DiaryEntryRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<DiaryEntries> Add(DiaryEntries diaryEntry)
{
await _context.DiaryEntries.AddAsync(diaryEntry);
await _context.SaveChangesAsync();
return diaryEntry;
}
}

EF Core Add-Migration generating extra column with ColumnName1

I have the following entities when I generate migration it creates two columns with name RestrictedCategoryId and RestrictedCategoryId1(FK). How to solve this issue to generate only one column with FK?
Note: I need OrderId in each entity.
`C#
public class Order
{
public Guid Id { get; set; }
public DateTime OrderDate { get; set; }
private List<Category> _categories;
public List<Category> Categories => _categories;
}
public class Category
{
public Guid Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public Guid OrderId { get; set; }
public Order Order { get; set; }
private List<RestrictionCategory> _restrictedCategories;
public List<RestrictionCategory> RestrictedCategories => _restrictedCategories;
}
public class RestrictionCategory
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid OrderId { get; set; }
public Order Order { get; set; }
public Guid CategoryId { get; set; }
public Category Category { get; set; }
public Guid RestrictedCategoryId { get; set; }
public Category RestrictedCategory { get; set; }
}
public class OrderConfiguration : IEntityTypeConfiguration<Order>
{
public void Configure(EntityTypeBuilder<Order> builder)
{
builder.HasKey(o => o.Id);
builder.Property(o => o.Id).IsRequired();
}
}
public class CategoryConfiguration : IEntityTypeConfiguration<Category>
{
public void Configure(EntityTypeBuilder<Category> builder)
{
builder.HasKey(c => new { c.Id, c.OrderId });
builder.Property(o => o.Id).IsRequired();
builder.Property(o => o.OrderId).IsRequired();
builder.HasMany(c => c.RestrictedCategories).WithOne(cr => cr.Category)
.HasForeignKey(cr => new { cr.CategoryId, cr.OrderId
}).OnDelete(DeleteBehavior.NoAction);
}
}
public class RestrictionCategoryConfiguration : IEntityTypeConfiguration<RestrictionCategory>
{
public void Configure(EntityTypeBuilder<RestrictionCategory> builder)
{
builder.HasKey(c => new { c.Id, c.OrderId });
builder.Property(o => o.Id).IsRequired();
builder.Property(o => o.OrderId).IsRequired();
builder.HasIndex(cr => new { cr.RestrictedCategoryId, cr.OrderId });
}
}
`
The entities resembles to actual ones.
Actually you get two additional columns:
RestrictedCategoryId = table.Column<Guid>(nullable: false),
RestrictedCategoryId1 = table.Column<Guid>(nullable: true), // <--
RestrictedCategoryOrderId = table.Column<Guid>(nullable: true) // <--
Apparently EF Core Foreign Key Conventions doesn't play well with composite keys, so you have to explicitly configure the relationship - similar to what you did for the other relationship, just since your model has no corresponding collection navigation property you have to use HasMany with generic type argument and no parameters, e.g. inside CategoryConfiguration:
builder.HasMany<RestrictionCategory>()
.WithOne(cr => cr.RestrictedCategory)
.HasForeignKey(cr => new { cr.RestrictedCategoryId, cr.OrderId})
.OnDelete(DeleteBehavior.NoAction);

How to access foreign key values on MVC view?

I'm having trouble accessing foreign key values in my view without using a partial.
I have tblProperty as Primary_Key and tblCustomer as foreign_key. I want to access the values of my foreign keys in my view but can't figure out why.
Model
public partial class tblProperty
{
public tblProperty()
{
this.Images = new HashSet<Image>();
this.tblCustomers = new HashSet<tblCustomer>();
}
public int propertyID { get; set; }
public string address { get; set; }
public string description { get; set; }
public virtual ICollection<Image> Images { get; set; }
public virtual ICollection<tblCustomer> tblCustomers { get; set; }
}
public partial class tblCustomer
{
public int customerID { get; set; }
public string name { get; set; }
public decimal contactNumber { get; set; }
public string notes { get; set; }
public Nullable<int> propertyID { get; set; }
public virtual tblProperty tblProperty { get; set; }
}
controller
public class propertyController : Controller
{
propertyDBEntities2 dc = new propertyDBEntities2();
public ActionResult List()
{
var properties = dc.tblProperties.Include(p => p.tblCustomers);
return View(properties.ToList());
}
public ActionResult Details(int id = 0)
{
var properties = dc.tblProperties.Include(p => p.tblCustomers);
tblProperty property = dc.tblProperties.Find(id);
tblCustomer customer = dc.tblCustomers.Find(id);
if (properties == null)
{
return HttpNotFound();
}
return View(dc.tblProperties.Find(id));
}
public ActionResult Create()
{
return View();
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Create(tblProperty e)
{
if (ModelState.IsValid)
{
using (dc)
{
dc.tblProperties.Add(e);
dc.SaveChanges();
}
}
return RedirectToAction("List");
}
view
(like model.name is trying to access name from tblCustomer)
#model myProject.tblProperty
#Html.DisplayFor(model => model.name)
tblProperty doesnt have name.
I guess you need
#Html.DisplayFor(model => model.tblCustomer.name)
But just debug it or use intellisense
EDIT:
In my project I create a dtoClass Data Transfer Object
So for my avl class I have a dtoAvl
avl Class:
public partial class avl
{
public avl()
{
this.cars = new HashSet<cars>();
}
public long avl_id { get; set; }
public Nullable<long> car_id { get; set; }
public Nullable<decimal> speed { get; set; }
// this class contain info regarding the road
public virtual manila_rto manila_rto { get; set; }
public virtual ICollection<cars> cars { get; set; }
}
I create a dtoAvl
public class dtoAvl
{
public long Avl_ID { get; set; }
public long? Car_ID { get; set; }
public string RoadName { get; set; } // came from manila_rto
public int Speed { get; set; }
}
My controler
List<dtoAvl> result = db.avls.Select(
r => new dtoAvl
{
Avl_ID = r.Avl_ID,
Car_ID = r.Car_ID,
Speed = r.Speed,
// here is a propery but can be a list
RoadName = r.manila_rto.name
}).ToList();
return PartialView(result);
View:
#model IEnumerable<dtoAvl>

Resources