jgozal
jgozal

Reputation: 1582

Add & Remove prefix to GUID via ModelBuilder conversion

I'm trying to add and remove a prefix to a GUID on each request to my service.

Something like this

 modelBuilder.Entity<MyEntity>()
                .Property(e => e.Id)
                .HasConversion(
                    v => PrefixConstant + v,
                    v => Guid.Parse(v.Substring(PrefixConstant.Length)));

Where PrefixConstant is just a string holding something like "ABC_". The idea is to store the id as a GUID, but return it with a prefix to the client.

The above hasn't been working too well with an error of id is of type uuid but expression is of type text

Upvotes: 2

Views: 460

Answers (2)

Ivan Stoev
Ivan Stoev

Reputation: 205649

The idea is to store the id as a GUID, but return it with a prefix to the client.

The implementation though does the exact opposite. The defined value conversion here

.Property(e => e.Id)
.HasConversion(
    v => PrefixConstant + v, // (1)
    v => Guid.Parse(v.Substring(PrefixConstant.Length)) // (2)
)

implies that the class property Id type is Guid, stored as string in the database, and using (1) for writing and (2) when reading the database value.

So all you need is to simply exchange the types and conversions, e.g. making the Id property type string

public class MyEntity
{
    public string Id { get; set; }
}

and configuring to/from database Guid conversion

.Property(e => e.Id)
.HasConversion(
    v => Guid.Parse(v.Substring(PrefixConstant.Length)),
    v => PrefixConstant + v
)

For more info, see the EF Core documentation of Value Conversions and ValueConverter<TModel,TProvider> class.

Upvotes: 3

Arman Ebrahimpour
Arman Ebrahimpour

Reputation: 4461

The reason of error is almost clear. You get error because you want to convert Guid to string and save it to database column whose type is Guid!

I think you choose a wrong option. HasConversion is suitable for situations where you want convert data and save converted data, but your intention is just displaying property to client in another way (Your concern here is about UI, not logic). So I think doing change in your model is very better option:

public class MyEntity
{
    private const string PrefixConstant = "ABC_";
    private Guid id;
    public string Id
    {
        set => id = Guid.Parse(value.Replace(PrefixConstant, string.Empty));
        get => $"{PrefixConstant}{id.ToString()}";
    }
}

It's just to show you the idea. Even this code is not a best practice if you use that as your DataModel because you shouldn't use your DataModel instead of ViewModel. My intention here as MyEntity is ViewModel not DataModel and you should pay attention to their differences and separate them from each other.

Upvotes: 1

Related Questions