Im amazed. I dont know exactly what detail but somehow this video seemed like a massive upgrade in production quality. Careful now. We might start to expect this from you from now on.
@zoran-horvatАй бұрын
@@elraito There are about five rules to configuring EF Core and those give you the power to map object models of immense complexity into an elegant and fast relational schema. The trouble is that even experienced developers stay at using about two out of five rules, and then struggle with issues of all kinds. Even to the point of blaming the Entity Framework for their failure, and avoiding to use it.
@jordanfarr3157Ай бұрын
🤯🤯🤯🤯🤯 okay you win. I'll join the Patreon.
@amakazor8632Ай бұрын
Hello Zoran! I have started watching your videos recently trying to expand my C# knowledge and they are an absolute goldmine. Thank you very much for producing content of this quality, showcasing this high of a skill level while still being easy to follow and learn from!
@Tesfamichael.GАй бұрын
Your lessons are all wonderful to me! You seem to be the Nicola Tesla of C#. живјели!
@AK-vx4dyАй бұрын
Glad you take this topic on the table, i also asked many times. I personaly had to use .HasConversion but from diffrent reason, i have a problem with consistent interpretation of datetime type, because sql type has no timezone info or even source info like DateTime in C# has, so i added conversion wich stored datetime as UTC always in database and EF done whole job. Value conversion are nice, but sometimes they make reporting from external tools harder (because there is no dictionary or mapping in database).
@Gonzo345Ай бұрын
I simply love I’m not alone loving EF Core. Thanks for this video and congratulations!
@handlez411Ай бұрын
This is awesome. You split my head open far too often!
@zoran-horvatАй бұрын
@@handlez411 Sorry, I find a lot of joy in doing that.
@handlez411Ай бұрын
@@zoran-horvat Love it
@peterriesz69Сағат бұрын
Great Video! It inspired me to try adding a MailAddress ValueConversion to a project I'm currently working on but I had to bail once as I realised I would no longer be able to query email addresses by host. Using the CultureInfo example, lets say we have book cultures fr, en-GB, en-US. Now we just want to retrieve all english (en) books. Previously this could have been achieved with books.Where(book => book.Culture.StartsWith("en")). I am pretty sure books.Where(book => book.Culture.TwoLetterISOLanguageName == "en") is going to throw. Using custom value conversion will limit your ability to query these fields with EF.
@cmdr_thruddАй бұрын
Another great video and also some good laughs. I never knew we could do value conversions, I'm going to have to try this in my next project. Thank you :)
@adiazwiseАй бұрын
Excellent approach, I will try to implement it in my projects.
@shmupfulАй бұрын
Great content, loved the convertion of PublicationDate to int
@vovcheable19 күн бұрын
i love your sense of humor
@ElOroDelTigreАй бұрын
Amazing as usual. This is top tier content.
@AndersBaumannАй бұрын
Indeed a good technique. Well done, Zoran!
@zoran-horvatАй бұрын
@@AndersBaumann You ended up in it.
@JonasMotiejauskasАй бұрын
Great video! It would also be very interesting to hear more about owned types and discriminations to have even more decoupled models and entities. Also how to best map immutable types / lists to support functional design
@Buutyful22 күн бұрын
hey zoran! thx for the video as always :) in any of your entities i see fk, why is that? do u use shadow props?
@conbag5736Ай бұрын
Excellent video as always Zoran. Yet, I do find parts of this implementatiom a little bit lacking in your usual elegance. I don't mean that as a critcism in any way - I certainly could not do it better - but there's a few observations which I think are worth making. Firstly, the pairing of EditionToString and StringToEdition struck me as potentially problematic. As it stands, when there are only two implementations of IEdition, it is fine. However, if there were more implementations, and you had to account for every one inside both switch statements - where each is exactly the inverse of the other - this seems like a recipe for bugs - where one type is inadvertently serialized/de-serialized as another. Secondly, the private property "PublicationKind". In the Configuration class, you are concerning yourself with setting the value of a private field. Under normal circumstances, you wouldn't ever do this - but you need to do it here - and worse, you use a magic stiring representing the property name to do so. This feels like we're breaking one of the cardinal rules of OOP here. The conversion of PublicationDate to/from an int is also a bit confusing. If the opposite of this rich-domain model is using simple primitive types - persistance is easy. DateTime in C# world maps to DateTime/DateTime2 in SQL world. Whereas here, we have to come up with an elaborate multiplication/division system just to ensure we get the correct type. Again, another superb video, but I think the commenters at the beginning of the video have a valid point. Persisting this is tricky.
@zoran-horvatАй бұрын
@@conbag5736 You are right about the edition persistence. I used formatting here to demonstrate the technique, but in reality I would split it into two columns - one for the enum and one for the accompanying number. Setting up the PropertyKind with a "magic string" is the only possibility,. EF is using reflection to access private fields and properties, but that means lambdas and nameof are inaccessible. It is common to use strings to specify properties in EF Core configurations. Regarding the dates to int conversions, it is not possible to avoid it. The domain model proposes incomplete dates, which cannot be persisted as any date type. That would require all three components of the date, but one or two might not be available.
@haraheiquedossantos4283Ай бұрын
I think it all depends which side you wanna be. The pure and "clean" domain models with "no" knowledge how it persists so far, but you have those complexities of transform to data/persistent models and converters. Or you could simply use data models (anemic domain models) in CRUD nature style without complexities. Which one to choose? It depends of which type of domain problems you are solving and complexity of the behaviors of your system. Great videos btw. Congrats 🙏
@zoran-horvatАй бұрын
@@haraheiquedossantos4283 Anemic models work fine on very small services with mostly CRUD-type requirements. As soon as domain rules start to appear, a proper domain model becomes a necessity.
@FolsetsАй бұрын
Thanks for the video!
@pl4gueisАй бұрын
Absolutely loved the video. My key take away is that proper design upfront makes for a pleasant development experience later. I lazily relied on C# Tooling to create migrations and stuff for me which works nice but makes integrating proper Design more complicated because you need DTOs. This approach forces to actually learn EF Core deeply and use it properly. Thanks for sharing. Its time to study EF Core in more detail. Quick question. How did you do that SQL Query in VSCode?
@zoran-horvatАй бұрын
EF Core is a powerful library. It also allows for a simple decoupling via interfaces, such as a custom IRepository. That extension I use in VS Code is SQL Server extension by Microsoft. It is very useful.
@Jojor11Ай бұрын
Ok i have to look more carefully into this topic. It feels like the last piece I need to really go into a more organized approach and build the code in terms of what the application does instead of everything going around how the data will be stored in DB, which has been a problem multiple times as the app evolves. Very interesting
@ScrotoTBagginsАй бұрын
Brilliant!!!
@cesarpinto3276Ай бұрын
Beautiful video. What's your opinion on this take with a functional design? Do you just drop EF Core for a document database?
@zoran-horvatАй бұрын
EF Core is designed to track entities, which makes it inappropriate for immutable models. That is a pity, because it has a powerful implementation of IQueryable.
@cesarpinto3276Ай бұрын
@@zoran-horvat That makes sense, and it is unfortunate. Will you be doing a video on persistence in a functional immutable design? I've seen all of your functional videos and courses and always have wondered how you would approach it
@zoran-horvatАй бұрын
@@cesarpinto3276 I plan to do something of that sort, but it is not a priority now. Simply, Dapper does that out of the box, mutable or immutable. However, I have a more realistic plan of showing a combination of mutable entities with immutable contained objects. That is a more interesting proposition in my view, and it is supported by EF Core via complex types and value conversions.
@nanny07Ай бұрын
Hi Zoran, thanks for the video! How about mongo? Should we use IBsonSerializer to achive the same results?
@zoran-horvatАй бұрын
@@nanny07 You can always choose a document database if the problem you are solving is of the document type.
@virideАй бұрын
Hi Zoran, great video! If I understand correctly, using this approach would make Dapper or database browsing using sql unusable (if I am wrong please correct me). Do you think that this approach would be worth it in production situations?
@zoran-horvatАй бұрын
@@viride I am using this in production code regularly. Regarding Dapper, it remains what it is. If you want to be the master of SQL and the schema, then Dapper is the way to go. If you wish to have more time with C# objects, then EF Core 8 is a powerful library that will help you develop the domain model.
@okcharles7Ай бұрын
Even when using Dapper, you can still use EF Core in design time, which means that the converting from runtime objects to table ones in this video, the first parameter in HasConversion(objectToRecordExpression, recordToObjectExpression), can be utilized when you update DB. After the time, you can use Dapper to query. However, mapping remains as your job, which just means your mapping code will be used instead of the second parameter of the HasConversion method. I think designing with EF Core design tools is recommendable even if you are a master of Db and query, especially in the case you are responsible for both code and DB. It can eliminate a lot of human errors in dealing with strings for queries throughout the application life cycle and, in result, you can save a lot of time.
@dobripopov8466Ай бұрын
Excellent approach! I am tired of looking at Clean architecture tutorials which advise you to abstract EF by creating custom IRepository and IUnitOfWork. EF Core has such a wonderful feature to map domain models to db. Why nobody uses it?
@pl4gueisАй бұрын
Most likely because Tutorials don't cover it and people don't read documentation :D
@zoran-horvatАй бұрын
There is a lot of dogma around the design. I don't like that at all. For example, many programmers dismiss the use of ORMs on the grounds that they cannot decouple the domain model from infrastructure. But they fail to see they don't need that decoupling. They will never benefit from such absolute decoupling, but they will rob their application from a myriad of useful optimizations.
@Adam-vg5yzАй бұрын
@@zoran-horvat Very interesting to see you say this! I have been struggling with this back and forth for weeks now. Prior to watching this video, I was convinced the best solution would be to have my domain objects injected with an IRepository interface, with the implementation in my infrastructure project. Then, I could have those Repositories handle the mapping between my domain models and my persistence models. I used to assume that Clean Architecture examples simply omitted the strict seperation between domain/persistence for brevity. Maybe I need to spend more time learning about EF Core and how much smarter it is than me!! This video has given me a lot to think about, and has gotten me very excited. Thank you Zoran :)
@zoran-horvatАй бұрын
@@Adam-vg5yz EF Core 8 has plugged an ancient hole in its own design with complex types. Now its mapping capabilities are so powerful that you can offload the entire mapping back and forth to it and only work with the domain objects.
@Rademcz27 күн бұрын
Would be also great to see how to query this. For example, what If I need to efficiently retrieve only books that are planned to be published this year? How do I get to execute the condition in db engine instead of fetching the whole tables?
@zoran-horvat27 күн бұрын
@@Rademcz I have a few videos in the queue that will cover querying by complex objects.
@icarohenrickАй бұрын
Thank you Thank you Thank you!!!!
@allinvanguardАй бұрын
Cool stuff! I'm curious, would this also have ended up with a resonably decent result when using the built in EF Core TPH / TPC mapping? Especially TPH sounds quite similar to your approach, but in this case you took over the steering wheel. Would EF have handled this similarly?
@zoran-horvatАй бұрын
@@allinvanguard You are right, I have applied TPH in combination with something that looks like EF Complex Type mapping. I plan more videos about dealing with record types in EF Core, which will shed even more light on that
@HenrryPires11 күн бұрын
good video
@Robert-yw5msАй бұрын
I have a question. How smoothly does this work with LINQ? For instance, if I do var americanBooks = await context.Books.Where(b => b.CultureInfo.Name == "en-US").ToArrayAsync() will EfCore be smart enough to translate my predicate into SQL, or will it pull everything into memory in order to filter?
@zoran-horvatАй бұрын
@@Robert-yw5ms Actually, you would use the CultureInfo in the LINQ query, and EF Corey would apply the same value transform to construct the SQL query for you. It works out of the box.
@Robert-yw5msАй бұрын
@@zoran-horvat Ah so I would do .Where(b => b.CultureInfo == new CultureInfo("en-US")) That's pretty neat.
@zoran-horvatАй бұрын
@@Robert-yw5ms Yes. That is an extremely useful feature in EF Core. Between the lines, which may not be obvious at first, the type you use must have a proper implementation of Equals which behaves the same as equality comparison of primitive values in the database. Otherwise, you might get rows back which you did not expect. In your example, SQL would compare a string "en-US" to what it finds in the database. Depending on the settings, that would even equal "en-us", small letters, in the database, but that is fine with us. The trouble would be if CiltureInfo.GetCultureInfo("en-us") is not equal to CultureInfo.GetCultureInfo("en-US"), which I think is not the case. You can imagine this duality of comparisons leading to troubles in certain cases.
Ай бұрын
Thank you for good stuff. One bite though 😂. At 9:44 I see the stuff I require from collegues during code reviews: when throwing try to give as many hints as possible. In this case arg exc telling what exactly edition type wasn't supported. And just few moment later, when converting string to edition, it's just "Unsupported edition format" 😢
@zoran-horvatАй бұрын
Actually, I do not advise showing string data in the log. You cannot tell if those data are subject to privacy concerns.
@dusanknezevic9072Ай бұрын
Great content! I did something similar in a project a few years ago in EF Core 6. Value conversions are just great. And I almost got laid off project because lead architect was furious I didn't use Unit Of Work and Repository interfaces wrapping DbContext and "hiding" EF Core 🤣like a plague. The last strawman argument of that architect for using Repository and UoW interfaces was that errors can happen when parsing unsupported data (they can always happen when using external data). EF Core 8 went above and beyond by adding ComplexType mappings and more cases of mappings, type conversions and other goodies. Your conversions of `Type` properties seem very similar to what EF Core does with TPH and TPC apporaches when mapping class hierarchies.
@zoran-horvatАй бұрын
@@dusanknezevic9072 Yes, my conversion of Type is the exact copy of what EF does in the similar situation.
@KubaSzostakАй бұрын
Thanks!
@zoran-horvatАй бұрын
Thank you!
@petervo224Ай бұрын
Sorry if I miss it in the video: Why prefer mapping to PublicationDate as int instead of date column?
@zoran-horvatАй бұрын
Because day or day and month parts might be missing. That was the customer's requirement. You cannot write a date value with its day being zero or the month being zero.
@petervo224Ай бұрын
Ah! Sound like replacing the missing parts with 01s or end day/month can be misleading and not acceptable by the requirements... Got it!
@zoran-horvatАй бұрын
@@petervo224 Yes, any of the substitutes could be the valid intended value, and then the information is lost.
@lukaszmatecki421814 күн бұрын
Why not Json for complex types?
@zoran-horvat14 күн бұрын
@@lukaszmatecki4218 Why move away from relational types in a relational schema? The queries are yet to come. Would you rather mix JSON and relationships in the same query?
@hosseinsanjabian164Ай бұрын
Well Done, i love you're Videos but this approach ( using too many complex object ) doesn't introduce overhead? like in scenario when we want get List (With Pagination) for each item in that list ef need to convert them to real object use you're conversion rules.
@zoran-horvatАй бұрын
@@hosseinsanjabian164 You would only use full domain objects in commands. In queries, you can strip the query down to only load the fields you will actually use in the result.
@goliafffffАй бұрын
Now I have another question. How to deserialize this model from request?
@zoran-horvatАй бұрын
@@goliafffff You mean load from the database? If that is the question, then mappings and conversions work both ways. You just get the objects back.
@goliafffffАй бұрын
@@zoran-horvat No. I mean we have rest API request to our app. And we should deserialuze incoming json to our oop model.
@zoran-horvatАй бұрын
@@goliafffff The OOP model you are referring to has constructors and factory methods. I don't see the problem in creating any of those objects.
@goliafffffАй бұрын
@@zoran-horvat How JSON serializer will decide which type of Edition to choose?
@zoran-horvatАй бұрын
@@goliafffff You choose based on JSON content. Don't fall into the trap of believing there is one JSON format for one set of types in the project. That may only be true in the simplest projects, which I do not cover in my videos.
@KubaSzostakАй бұрын
✨
@AK-vx4dyАй бұрын
About IEdition... why do not add ToString, FromString or smillar methods to do interface and concrete types will be responsible to implement such operations ? Also i have dillema what to do if we get some garbage or unsuported format from DB, exception may catch users in very strange places and/or inside some multistep operation with hard to understand error.Defaulting to some safe value is also not ideal... I don't know it is good solution here, but.... Aproach of converting at EF level has one big advantage - consistency in behaviour without risking that next "genius" will bring own ideas ;)
@zoran-horvatАй бұрын
@@AK-vx4dy Adding conversion to the interface would burden its implementers with guaranteeing uniqueness and parsability, schema evolution, backward compatibility, and a few other things they should never be responsible for. There is also the question of who would parse the strings.
@AK-vx4dyАй бұрын
@@zoran-horvat Wise points. I would not trust them ;) However how to do not allow them to add new incarnations of such interace without other party expaning conversion methods (Uncle Bob mubling OCP in the corner ;)? As i understand it will throw at runtime in this implementation ?
@terjeengelbertsen9215Ай бұрын
Any source code available?
@zoran-horvatАй бұрын
@@terjeengelbertsen9215 Yes, on Patreon. There is the link in the description.
@adambickford8720Ай бұрын
This feels bad to me. If you're going to violate normal forms with things like `edition`, why create a limited de/serialization format instead of just throwing it in json? At least as json things like schema migration are well understood and you could still query it in postgres.
@zoran-horvatАй бұрын
@@adambickford8720 How did I violate normal forms?
@adambickford8720Ай бұрын
@@zoran-horvat In the case of `SeasonalEdition` you are storing 2 values in 1 column which is why you have to split it. Why not just use json and you don't have to worry about all kinds of de/serialization issues?
@zoran-horvatАй бұрын
@@adambickford8720 JSON is hard to query in a SQL database. It is also an overkill compared to a primitive column type in a table where all other columns already have simple types.
@adambickford8720Ай бұрын
@@zoran-horvat agreed, which is why breaking normal forms feels bad. but if we must, json has first class support in postgres :) I disagree its overkill. This approach causes you to write custom de/serializers for every new type. That's begging for injection attacks. And if you have nested objects, good luck!
@marvinxulu7816Ай бұрын
You thinking defets most people it's like you what people do 😂 you make me feel dumb but i still watch😢
@n00bjeАй бұрын
Interesting concepts. I get why you use them, but I feel like this is becoming an over engineered project that is very restrictive, difficult to hand over to inexperienced people, or people with a limited knowledge of the domain/framework. Adding a new class that implements IEdtion is easy, but it's not obvious for new people that there are also two conversion functions you have to change, and probably some work/mapping in your API and front-end. I would be very tempted to replace IEdition and its implementations with just a string, or a FK to a (power)user-editable lookup table. Having to contact the developer and wait for a new release just so you can enter a new edition like "anniversary", "special" or "limited" also seems so unnecessary. Especially when you have to go through a vendor, get a quote, have it approved, etc. I'd probably replace PublicationKind with a FK to another user-editable table as well, because I just *know* that Published, Planned and NotPlannedYet is not going to be enough eventually.
@zoran-horvatАй бұрын
@@n00bje I think your fear of other people's ignorance is exaggerated. People know a lot. On the other hand, I find a great error in your idea of stringifying the domain model out of fear for how it would be persisted. The entire persistence configuration for that polymorphic type is located in just one place, as it should be. Changing the domain model is expected, and welcome, and it must be accompanied with the corresponding modifications at the edges of the system (persistence, serialization, DTOs, service contracts, etc.). We just don't give up programming principles because there exists a database. The idea of turning the PublicationKind into an entity has no justification from the point of view of the relational schema modeling.
@ldeeroselАй бұрын
What about validation? In your logic a phone number can be "hello there!"
@n00bjeАй бұрын
@@ldeerosel I create my own attributes that inherit from System.ComponentModel.DataAnnotations.ValidationAttribute, or inherit from IValidatableObject, or use the FluentValidation nuget package.
@zoran-horvatАй бұрын
@@ldeerosel I have skipped many small parts because they would obscure the principal message of the demo. However, in production code, you would have to install those back, so you are right. Anyway, those things do not affect what this video is demonstrating, in respect to persistence and value conversions with EF Core.
@gligomАй бұрын
I think that i start to cry, I realize that I am too stupid for such content. I see every day applications written with so much bad code, out off any principles, out of any patterns and out of common sense, but they work, are stupid simple and … they make money, not just now, for years. The developers just make them work, they don’t care about all the “theory”, they just do! And anyway for each principle, good practice, you will find 10 “experts” that will tell you why is bad to use.. One lesson that I learned, theory and tutorial examples don’t apply in real life applications.
@zoran-horvatАй бұрын
@@gligom Theory applies to practice but majority of practitioners don't know it.
@eugene5096Ай бұрын
dont cry, for 16 years + i also never saw and had no change to write something like this. Im trying Zorans approaches step by step in small pieces. In real life apps you would not need this or it will be done differently - its a reality.
@zoran-horvatАй бұрын
@@eugene5096 I strongly disagree with this opinion. It reminds me of people saying they don't need theory of algorithms, where in fact they don't know it. The reality is they miss the opportunity to apply it, for they don't know the opportunity even if it slaps them in the face, and then deliver sub par solutions. The same applies to database design or any other area of our expertise. You can know the theory, apply it, and deliver a superb solution. Or you can struggle with a solution that cannot handle the whole bunch of expectations and requests and blame whoever else, such as customers, users, managers, or the programming itself.
@ivanek333Ай бұрын
6:18 Why not just add two methods in IEdtition, for converting from and to the database? Isn't it, like, the whole point of abstraction? Overall, the solution seems like halfway to just straight json converting everything. And well, for some tasks it actually may be useful, but from my vague understanding, the advantage of having everything separate in the database (instead of just converting a whole object into a json string or whatever you're using) is the ability to grab only the required rows from the database, which is not possible with your solution (or it would require string processing in sql calls, with great potential for bugs and accidental breaks) One way it could work though, is that for each interface/abstract class/ you could also make an additional enum column in the database, which specifies the concrete type, and in your interface you can add another two methods for setting and checking if that enum value corresponds to this type. That way you keep all the benefits of abstraction (i.e. not changing orm-related code each time you add a new child class), but also have the ability to select rows with only those types that you need. 12:28 Oh, yeah, that's what i was talking about. 14:26, Well, developing my thought, you can also specify the return type in your interface (instead of just going all strings), so if you really want to harness the power of fitting everything to an int column, you can force child classes to convert their values to int too. (well, the one who would be forced to convert to int is the one implementing methods in child classes) Am I wrong?
@zoran-horvatАй бұрын
@@ivanek333 It is not a good idea to add persistence configuration to the interface, because that would require the interface to know the structure of all its implementing types and, worse yet, each implementing type would need to know the structure of every other. I thought it was a silly idea at first, but now I think it is a uniquely catastrophic idea.
@ivanek333Ай бұрын
@@zoran-horvat What do you mean? Why would "interface need to know the structure of all its implementing types"? Maybe I wasn't clear enough, because that's the opposite of what I was talking about. In interface you add two methods: string ConvertToDatabase(), and ISomeInterface ConvertFromDatabase(string value). And in those methods you implement those conversions you did at 7:41. And, I know, ConvertFromDatabase won't just work as simple as that, because to call it you need an instance of a class in the first place, so maybe you can work around by making it static and then register it somewhere else, and so on and on. My main point is that, the only reason you have abstraction tools is to do abstraction. If you have classes hidden behind interface, you shouldn't go and explicitly define mappings for each of them in some place, other than class itself.
@zoran-horvatАй бұрын
@@ivanek333 Give me the signature of the method on the interface that does the conversion.
@ivanek333Ай бұрын
@@zoran-horvat oh no, it seems like youtube had some error and didn't post my comment
@ivanek333Ай бұрын
probably it doesn't like links to pastebin?
@goliafffffАй бұрын
Looks interesting. But in real production application I will never ever do this. It's over complicated.
@zoran-horvatАй бұрын
@@goliafffff What would you do?
@goliafffffАй бұрын
@@zoran-horvat Plain anemic model.
@zoran-horvatАй бұрын
@@goliafffff We've already been there. It is trendy to repeat mistakes of the past but, honestly, you won't impress anyone with that. Have you impressed anyone with that?
@liamhotspur9182Ай бұрын
Think first, database first!
@zoran-horvatАй бұрын
@@liamhotspur9182 I strongly disagree. However, I'd say that database design remains as important as ever.
@liamhotspur9182Ай бұрын
@@zoran-horvat Why? Because it is supposed to be more agile?
@zoran-horvatАй бұрын
@@liamhotspur9182 Database first? No. It's the opposite for all I am seeing in practice.
@robertmrobo8954Ай бұрын
Ofcoz I liked the video content, but eish.. 🤦♂🥺
@zoran-horvatАй бұрын
@@robertmrobo8954 Was it too advanced, or...?
@JonathanPeelАй бұрын
And of course, you could use an event sourcing and never need to worry about how your domain model maps to a table.
@zoran-horvatАй бұрын
@@JonathanPeel First, it is not true. You will still maintain the schema for querying. Second, it is preposterous to assume that maintaining a relational schema is some kind of a problem. It is a solution to a problem, which requires work. Any other solution requires work, too. Not every system will benefit from event sourcing, naturally. Would you still apply event sourcing to an obviously relational problem? I generally dislike that tone which presumes event sourcing is a cure for all ailments. I can confirm that it usually comes from tragically incompetent programmers who don't even understand event sourcing, but needed something to run away from relational design which they also don't know.
@JonathanPeelАй бұрын
@@zoran-horvat I appreciate this reply 👍🏻 I am very happy in a relational world, a lot more comfortable than with a document DB. But that might be familiarity. The event sourcing is kind of the next technique I want to try to understand properly.
@shadowsirАй бұрын
For IEdition, I'd also keep a "discriminator" column (e.g. edition_discriminator or edition_type) to map the string value in the DB to the proper concrete class. Alternatively something like $"OrdinalEdition: {ordinal.Number}", $"SeasonalEdition: {Enum.GetName(seasonal.Season)} {seasonal.Year}", to keep it in a single column. This makes the conversion less "magic" as well. You never know if you're going to need a way to convert "1" to an OrdinalEdition or to a potential future type "AuthorDefinedEdition" where an author can enter any kind of string.
@zoran-horvatАй бұрын
You are right. I would go with a varchar + int columns, similar to PublicationInfo. One column would store the enum value or null, and the other would store the year number or edition number. That format is 100% deterministic.