la-yumba / functional-csharp-code

Code samples for Functional Programming in C#
MIT License
587 stars 183 forks source link

Can we create an Entity framework model using custom types? #21

Open MrYossu opened 3 years ago

MrYossu commented 3 years ago

Take the Age type from chapter 3 as an example (source code).

Suppose I want to create a Person class, that EF will map to a table...

  public class Person
  {
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public Age Age { get; set; }
  }

I don't want Age to be mapped to a table, but can't see a way of convincing EF Core about this.

Anyone any ideas? Can we even use custom types with EF Core?

Thanks

la-yumba commented 3 years ago

That's an interesting question, and hopefully someone who uses EF more than me will give a good answer... My feeling is that you may have to have 2 fields, the public Age Age field that is a computed property, and say private int AgeInternal that maps to the DB... In any case, EF is not FP-oriented in the least, so you're bound to have more issues of this kind if you want to combine EF and FP... but that doesn't mean that it can't work to some extent.

MrYossu commented 3 years ago

@la-yumba Thanks for the reply. Not sure how a private property would work, as EF populates public properties.

However, your reply led me to a question I was about to ask...

Whenever I read material on FP, including your book, Scott Wlaschin's excellent "Domain Modeling Made Functional" (well worth reading, even for a C# programmer) and others, I always see data access code done with SQL. Maybe I'm spoilt, but I've been using Entity Framework for years, and the thought of losing the elegance and simplicity of Linq, and going back to writing SQL makes me shudder.

Do you really use SQL? Isn't there an FP way of using an OR/M?

Thanks again.

josephshilo commented 3 years ago

EF has a NotMapped attribute that you could apply to the Age property.

MrYossu commented 3 years ago

@josephshilo Thanks for the reply, but that only gets me part-way. I would still need to have a public property that EF could map to a database column, as well as a way of making that inaccessible for any other code, forcing them to use the Age property. Can't see how that could be done.

WarBorg commented 2 years ago

@MrYossu does this help you: https://www.learnentityframeworkcore.com/configuration/fluent-api/ignore-method ?

if not, I'm sorry but I don't understand your scenario very well

MrYossu commented 2 years ago

@WarBorg Thanks for the reply, but I'm not sure how that link helps.

The scenario is very simple. I want to have a custom type for (say) an Age property, so instead of using an int, I would use a custom Age class that includes a constructor that validates the age being passed in. However, I don't want Age to be mapped to a linked table, I want EF to map it to an int column in the table.

I want to know if this can be done with EF Core. @la-yumba suggested a private property and @josephshilo followed up by suggesting marking Age as NotMapped, but in both of these cases I am still left with the problem of having some property that EF can map to an int column on the table, without it requiring a separate table for Age.

Is that any clearer? Thanks again.

WarBorg commented 2 years ago

@MrYossu ahh ok now I think I get it, you want to use the ValueObject pattern: please read here how this can be done in EF Core, hope this helps:

https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/implement-value-objects

MrYossu commented 2 years ago

@WarBorg Thanks, that looks promising. I'm going to have to do a bit of reading!