C
C#ā€¢10mo ago
sheru

ā” Retrieving GUID from db with EF core returning 0s

Hi, I'm new to EF core and I don't understand why this issue occurs. So the data in db is fine. But when calling this:
[HttpGet]
public virtual async Task<ActionResult<IEnumerable<TReadDto>>> GetAll(
[FromQuery] QueryOptions queryOptions
)
{
return Ok(await _baseService.GetAll(queryOptions));
}
[HttpGet]
public virtual async Task<ActionResult<IEnumerable<TReadDto>>> GetAll(
[FromQuery] QueryOptions queryOptions
)
{
return Ok(await _baseService.GetAll(queryOptions));
}
replacing all T with OrderReadDto which is this:
public class OrderReadDto
{
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
public class OrderReadDto
{
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
The returned data is this:
[
{
"userId": "00000000-0000-0000-0000-000000000000",
"status": "Processing"
}
]
[
{
"userId": "00000000-0000-0000-0000-000000000000",
"status": "Processing"
}
]
Any idea? Thanks in advance.
27 Replies
Angius
Angiusā€¢10mo ago
If it's a DTO, why does it have attributes specific for database entities...? Also, how do you get that data? The code, specifically
sheru
sheruā€¢10mo ago
oops yeah it wasn't supposed to be there
public async Task<IEnumerable<TReadDto>> GetAll(QueryOptions queryOptions)
{
var result = await _baseRepo.GetAll(queryOptions);
return _mapper.Map<IEnumerable<TReadDto>>(result);
}
public async Task<IEnumerable<TReadDto>> GetAll(QueryOptions queryOptions)
{
var result = await _baseRepo.GetAll(queryOptions);
return _mapper.Map<IEnumerable<TReadDto>>(result);
}
public async Task<IEnumerable<T>> GetAll(QueryOptions queryOptions)
{
return await _dbSet.ToArrayAsync();
}
public async Task<IEnumerable<T>> GetAll(QueryOptions queryOptions)
{
return await _dbSet.ToArrayAsync();
}
Angius
Angiusā€¢10mo ago
Ah, oof, repository pattern Well, I don't see the DTO being used anywhere Ah, nevermind You're doing the mapping... client-side With... automapper? I'd say it's something wrong with the automapper, then Perhaps there's no mapping between TRead and TReadDto
sheru
sheruā€¢10mo ago
yeah with automapper... I will recheck the mapper but I do have Order -> OrderReadDto. However in OrderReadDto I only wanted the UserID from User object instead of the whole user details. I think I have done it wrongly but I'm not sure how to do it correctly
namespace WebApiDomain.Entities;

public class Order : BaseEntityWithId
{
public OrderStatus Status { get; set; }
public User User { get; set; }
public List<OrderProducts> OrderProducts { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum OrderStatus
{
Shipped,
Processing
}
namespace WebApiDomain.Entities;

public class Order : BaseEntityWithId
{
public OrderStatus Status { get; set; }
public User User { get; set; }
public List<OrderProducts> OrderProducts { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum OrderStatus
{
Shipped,
Processing
}
public class OrderReadDto
{
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
public class OrderReadDto
{
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
Angius
Angiusā€¢10mo ago
Does BaseEntityWithId have a UserId property of Guid type? Or do you map it through User, with User.Id?
sheru
sheruā€¢10mo ago
So what I did was, I retrieved the user id from JWT via HTTP context and then GUID parse'd it. then added it manually to OrderCreateDto I wrote below. So now OrderProduct doesn't actually have an user object. And Order has User in it for the id but I suppose it actually contains the whole User instead of just the id... BaseEntityWithId:
public class BaseEntityWithId : BaseEntity
{
public Guid Id { get; set; }
}
public class BaseEntityWithId : BaseEntity
{
public Guid Id { get; set; }
}
and User:
public class User : BaseEntityWithId
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public string Avatar { get; set; }
public string Address { get; set; }
public string Password { get; set; }
public byte[] Salt { get; set; }
public Role Role { get; set; }
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum Role
{
Admin,
User
}
public class User : BaseEntityWithId
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public string Avatar { get; set; }
public string Address { get; set; }
public string Password { get; set; }
public byte[] Salt { get; set; }
public Role Role { get; set; }
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum Role
{
Admin,
User
}
Order (not dto):
public class Order : BaseEntityWithId
{
public OrderStatus Status { get; set; }
public User User { get; set; }
public List<OrderProducts> OrderProducts { get; set; }
}
public class Order : BaseEntityWithId
{
public OrderStatus Status { get; set; }
public User User { get; set; }
public List<OrderProducts> OrderProducts { get; set; }
}
DTO for creating order:
public class OrderCreateDto
{
public List<OrderProductsDto> ProductsAndAmount { get; set; } // List of product IDs
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
public class OrderProductsDto
{
public Guid ProductId { get; set; }
public int Amount { get; set; }
}
public class OrderCreateDto
{
public List<OrderProductsDto> ProductsAndAmount { get; set; } // List of product IDs
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
public class OrderProductsDto
{
public Guid ProductId { get; set; }
public int Amount { get; set; }
}
if my assumption is correct is it possible somehow to get only the user id in the dto somehow....
Angius
Angiusā€¢10mo ago
If the mapping in the automapper is correct, yes Or you can just use a .Select() and not be at automappers black box of a mercy
sheru
sheruā€¢10mo ago
Yea I do have this in my mapper profile
CreateMap<Order, OrderReadDto>();
CreateMap<Order, OrderReadDto>();
So i thought maybe this would work in the conversion
public class Order : BaseEntityWithId
{
public OrderStatus Status { get; set; }
public User User { get; set; }
public List<OrderProducts> OrderProducts { get; set; }
}
public class Order : BaseEntityWithId
{
public OrderStatus Status { get; set; }
public User User { get; set; }
public List<OrderProducts> OrderProducts { get; set; }
}
public class OrderReadDto
{
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
public class OrderReadDto
{
public Guid UserId { get; set; }
public OrderStatus Status { get; set; }
}
I have to google how to use Select... I just learned this whole web development in c# thing 2 weeks ago
Angius
Angiusā€¢10mo ago
It should work, yeah But you're using... TReadDto? Whatever that is? And the mapping is to OrderReadDto
sheru
sheruā€¢10mo ago
TReadDto is just a placeholder for the base service/etc so that it knows it will accept/return type of OrderReadDto/UserReadDto etc etc it's magic to me
Angius
Angiusā€¢10mo ago
A generic repository...?
sheru
sheruā€¢10mo ago
yes
Angius
Angiusā€¢10mo ago
I mean, yeah, it's way overcomplicated Generic repository is just reimplementing what EF already gives you
Angius
Angiusā€¢10mo ago
This is a generic repository
sheru
sheruā€¢10mo ago
like this is what is in my baserepo for example
public class BaseRepo<T> : IBaseRepo<T>
where T : class
{
private readonly DbSet<T> _dbSet;
private readonly DatabaseContext _context;

public BaseRepo(DatabaseContext dbContext)
{
_dbSet = dbContext.Set<T>();
_context = dbContext;
}

public virtual async Task<T> CreateOne(T entity)
{
await _dbSet.AddAsync(entity);
await _context.SaveChangesAsync();
return entity;
}

public async Task<bool> DeleteOneById(T entity)
{
_dbSet.Remove(entity);
await _context.SaveChangesAsync();
return true;
}

public async Task<IEnumerable<T>> GetAll(QueryOptions queryOptions)
{
return await _dbSet.ToArrayAsync();
}

public virtual async Task<T?> GetOneById(Guid id)
{
return await _dbSet.FindAsync(id);
}

public async Task<T> UpdateOneById(T updatedEntity)
{
_dbSet.Update(updatedEntity);
await _context.SaveChangesAsync();
return updatedEntity;
}
}
public class BaseRepo<T> : IBaseRepo<T>
where T : class
{
private readonly DbSet<T> _dbSet;
private readonly DatabaseContext _context;

public BaseRepo(DatabaseContext dbContext)
{
_dbSet = dbContext.Set<T>();
_context = dbContext;
}

public virtual async Task<T> CreateOne(T entity)
{
await _dbSet.AddAsync(entity);
await _context.SaveChangesAsync();
return entity;
}

public async Task<bool> DeleteOneById(T entity)
{
_dbSet.Remove(entity);
await _context.SaveChangesAsync();
return true;
}

public async Task<IEnumerable<T>> GetAll(QueryOptions queryOptions)
{
return await _dbSet.ToArrayAsync();
}

public virtual async Task<T?> GetOneById(Guid id)
{
return await _dbSet.FindAsync(id);
}

public async Task<T> UpdateOneById(T updatedEntity)
{
_dbSet.Update(updatedEntity);
await _context.SaveChangesAsync();
return updatedEntity;
}
}
bro to be honest i wish i can just go back to writing typescript for webdev but I committed to this
Angius
Angiusā€¢10mo ago
Yeah, you're just reimplementing stuff that already exists Literally taking a spoon and making a spoon out of it
sheru
sheruā€¢10mo ago
unfortunately i am required to do things this way šŸ« 
Angius
Angiusā€¢10mo ago
Ah, oof, my condolences
sheru
sheruā€¢10mo ago
i'm so lost at this point i kinda wish that restrating my pc would somehow solve this problem
Angius
Angiusā€¢10mo ago
In that case, not sure how much of a help I'll be. I was never a fan of complexity for the sake of complexity, never used generic repositories
sheru
sheruā€¢10mo ago
no worries, you tried and I'm thankful for that
Angius
Angiusā€¢10mo ago
Ah, wait, I have an idea Two, rather One: add a UserId property to your Order, of type Guid This will be the foreign key, and automapper should pick it up Two: Since the mapping is done on the client instead of on the database, you might have to .Include(order => order.User) to actually load the data that can later be mapped
sheru
sheruā€¢10mo ago
Ok I will try that šŸš™ šŸ’Ø also i have just realised that User id in the actual user db is stored as id and not userid might it be that ef core somehow got confused
Angius
Angiusā€¢10mo ago
Yeah, but automapper will pick it up User.Name will be put in UserName, User.Role.Color will go into UserRoleColor and so on So that one should not be an issue
sheru
sheruā€¢10mo ago
So i just added step one did new migration and db update and it works but why?
Accord
Accordā€¢10mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.