C
C#4mo ago
schwartzmj

Catching unique constraint violations and returning the field(s) violating it in a "service" class

I'm working on creating a pretty standard API in .NET Core using EF. I have various fields in my project (e.g. slug) that need to be unique. I'd like to be able to tell the user that the "slug" field is already taken when they try to create/update. I've searched around and found some relatively complex solutions and I'm just wondering if I'm missing something simpler. Is there a general best practice surrounding this that I'm missing? I had some hope that there was something built in to EF Core for this.
18 Replies
Anton
Anton4mo ago
You generally run a query manually to check it
schwartzmj
schwartzmjOP4mo ago
public async Task<Result<PostDto>> CreatePost(PostUpsertDto newPostDto)
{
try
{
var newPost = await dbContext.Posts.AddAsync(newPostDto.ToEntity());
await dbContext.SaveChangesAsync();
return Success(PostDto.FromPost(newPost.Entity));
} catch (DbUpdateException)
{
return Failure<PostDto>(new ErrorDetails("...", ErrorCode.Conflict));
}
}
public async Task<Result<PostDto>> CreatePost(PostUpsertDto newPostDto)
{
try
{
var newPost = await dbContext.Posts.AddAsync(newPostDto.ToEntity());
await dbContext.SaveChangesAsync();
return Success(PostDto.FromPost(newPost.Entity));
} catch (DbUpdateException)
{
return Failure<PostDto>(new ErrorDetails("...", ErrorCode.Conflict));
}
}
i've created a few helpers as you can see here, but i'm hoping to return some helpful information in my exception this could still error after checking though (theoretically — if one was created in between)
Anton
Anton4mo ago
You could do that too, but the issue is that you might have to parse the error to get info on what exactly was violated, for which field, and then map it back to the property It can't be verified programmatically You can check the error code in the exception though
schwartzmj
schwartzmjOP4mo ago
Ok, thanks. So I might be best off making some sort of helper and re-using it in my services like this?
Anton
Anton4mo ago
There's a code that corresponds to constraint violations for example You generally validate before inserting because you will likely lose information if you just try to insert lose context, i mean e.g. you can't easily know for which field, or for which value the error was and parsing the error message is not something you should rely on
schwartzmj
schwartzmjOP4mo ago
So basically, do a check on the slug and return a helpful error if it is taken. If the unlikely scenario happens where its taken right after the check, then just return a generic exception since it will probably never happen anyway
Anton
Anton4mo ago
yeah probably
schwartzmj
schwartzmjOP4mo ago
(if i wanted to simplify this and keep moving)
Anton
Anton4mo ago
consider using a transaction possibly afaik it's isolated, aka if some other thread updates the tables in the middle, your logic won't see the new things until the transaction ends I used to have helpers for fluent validation for this on the previous job, but it was horribly complex the interface was really simple but the implementation was insane so I don't recommend that
schwartzmj
schwartzmjOP4mo ago
Yeah I can imagine... I appreciate the help. I think I'll just add the unique checks before the create/update and call it a day
Angius
Angius4mo ago
There's a nice library that makes EF error handling more sane. You can actually catch a UniqueConstraintViolationError instead of having to unwrap the inner exception and checking the code with magic numbers and what not https://github.com/Giorgi/EntityFramework.Exceptions
schwartzmj
schwartzmjOP4mo ago
Thanks — I saw this while I was searching around but I'm hesitant to add libraries without understanding all my options, but I'll look more into it
Anton
Anton4mo ago
So someone did the dirty work of parsing the exceptions huh
Angius
Angius4mo ago
ye
Anton
Anton4mo ago
This is how those errors should be by default imo It's probably not the default because it's not free The db engine just gives you a string and a code probably
Angius
Angius4mo ago
yeah
schwartzmj
schwartzmjOP4mo ago
yea - i was hoping that this just existed in EF and I wasn't finding it I appreciate the help!
Anton
Anton4mo ago
you're welcome
Want results from more Discord servers?
Add your server