C
C#10mo ago
Bordin

Models&sql

Hello, i created three new models: Tag UserTags PostTags the usertags and posttags were meant to hold a many to many relation between post/users and tags however idk why after applying migration only one table was created and it includes UserId and PostId even tho the PostId is not in the Tag model
public class Tag
{
[Key]
public required int TagId { get; set; }
public required string TagName { get; set; }

public int UserId { get; set; }
public DateTime CreatedDate { get; set; }
public Tag()
{
CreatedDate = DateTime.Now;
}
public virtual User? User { get; set; }
}
public class Tag
{
[Key]
public required int TagId { get; set; }
public required string TagName { get; set; }

public int UserId { get; set; }
public DateTime CreatedDate { get; set; }
public Tag()
{
CreatedDate = DateTime.Now;
}
public virtual User? User { get; set; }
}
The userId is just to keep track of who added the tag
No description
21 Replies
Bordin
BordinOP10mo ago
the jobId is the postid could it be because i added
public virtual ICollection<Tag>? Tags { get; set; }
public virtual ICollection<Tag>? Tags { get; set; }
to the Job model?
Angius
Angius10mo ago
If you want many to many between tag and user both the tag and the user need to have a collection of the other So tag needs a collection of users, and user a collection of tags The way you have it it's a one to many (also, remove the virtual. It implies lazy loading and lazy loading bad)
Bordin
BordinOP10mo ago
but i need some lazy loading
Jimmacle
Jimmacle10mo ago
for? afaik the main issue is lazy loading can't be asynchronous and it's not obvious that accessing a lazy loaded property could take a (relatively) long time
Bordin
BordinOP10mo ago
Ok so how can i achieve it manually? like if i needed to in some services
Angius
Angius10mo ago
Why? Load data eagerly Project unto DTOs Get all the data you need, and only the data you need, in a single db round trip
Bordin
BordinOP10mo ago
im confused, isnt that what lazy loading does
Angius
Angius10mo ago
No Lazy loading will load the user first, in one query Then, when you try to display blogpost by this user, it will query the db again Then, for each post, it will query again for its tags Instead of eagerly querying for the user, their posts, and those posts' tags, in a single database query And if you use a select, or some other projection method, you can even prevent it from querying for user password and email when they're not needed
Bordin
BordinOP10mo ago
are you writing sql manually
Jimmacle
Jimmacle10mo ago
no, you can do this in EF with normal linq for example
public record Response(
string Title,
DateTimeOffset DueDate,
int PeriodDays,
List<EmployeeNumber> AssignedTo,
List<EmployeeNumber> NotifiedPastDue,
ReminderStatus Status,
bool IsEnabled);

public static async Task<Result<Response>> Handle(Query request, PortalDbContext db, TimeProvider clock, CancellationToken cancellationToken)
{
var reminder = await db.Reminders.AsNoTracking()
.Where(x => x.Number == request.Number)
.Select(x => new Response(
x.Title,
x.Due,
x.DefaultFrequencyDays,
x.AssignedTo.Select(e => e.Number).ToList(),
x.NotifiedIfOverdue.Select(e => e.Number).ToList(),
x.GetStatus(clock.GetLocalNow()),
x.IsEnabled))
.SingleOrDefaultAsync(cancellationToken);

return reminder ?? Result<Response>.Fail("Reminder not found.");
}
public record Response(
string Title,
DateTimeOffset DueDate,
int PeriodDays,
List<EmployeeNumber> AssignedTo,
List<EmployeeNumber> NotifiedPastDue,
ReminderStatus Status,
bool IsEnabled);

public static async Task<Result<Response>> Handle(Query request, PortalDbContext db, TimeProvider clock, CancellationToken cancellationToken)
{
var reminder = await db.Reminders.AsNoTracking()
.Where(x => x.Number == request.Number)
.Select(x => new Response(
x.Title,
x.Due,
x.DefaultFrequencyDays,
x.AssignedTo.Select(e => e.Number).ToList(),
x.NotifiedIfOverdue.Select(e => e.Number).ToList(),
x.GetStatus(clock.GetLocalNow()),
x.IsEnabled))
.SingleOrDefaultAsync(cancellationToken);

return reminder ?? Result<Response>.Fail("Reminder not found.");
}
Bordin
BordinOP10mo ago
so you just add select method where are you achieving lazy loading? ah i see it can you use ,include instead?
Jimmacle
Jimmacle10mo ago
i'm not achieving lazy loading, that's the point lazy loading is bad i'm eagerly loading exactly what i need in a single query, and yes you can .Include as well if you want the whole related entity without explicitly selecting it
Bordin
BordinOP10mo ago
Okay so i have this
public virtual Role? Role { get; set; }
public virtual Role? Role { get; set; }
in my user, and 2 days ago i was having difficulty lazy loading the role name inside the Role entity it didn't load until i used .include in my query so what am i doing wrong if it should lazy load on its own??
Jimmacle
Jimmacle10mo ago
you aren't using the right terminology do not use lazy loading at all what we're suggesting is not lazy loading
Bordin
BordinOP10mo ago
yeaa i know but i just was wondering what i am doing wrong because it should lazy load right?
Jimmacle
Jimmacle10mo ago
no idea, i don't use lazy loading because it's bad
Bordin
BordinOP10mo ago
also i like the select query, it kindof also remove the need for mapping resources
Jimmacle
Jimmacle10mo ago
either .Include in your query or explicitly reference it in a .Select or if you always want it 100% of the time, you can configure it to be included automatically
Bordin
BordinOP10mo ago
ah i just realized why it didnt lazy load i think i didnt include it in the resources damn lol
Jimmacle
Jimmacle10mo ago
i'm really confused what you're referring to as lazy loading
Bordin
BordinOP10mo ago
nevermind, but i got your point and ill remove the virtual and start using .select thank you
Want results from more Discord servers?
Add your server