• (nodebb)

    #1) Yes, that code stinks...

    #2) Generics are a pale comparison to proper templates. Consider a program for the computer to play tic-tac-toe. To make it determinate, the computer will always pick the top-most/left-most square that ties in the evaluation process. Using templates, it is possible to reduce this to 100% compile time, so that the actual code consists of nothing but "cout<<" statements to print the board after each turn --- Try that with puny generics.

  • (nodebb)

    Repository pattern is good but not always needed. EF basically is a repository pattern itself so you're wrapping the wrapper.

    That code however, yikes.

  • (nodebb) in reply to TheCPUWizard

    From my understanding, templates primarily solve the problem of creating generic abstractions without requiring run-time type system overhead.

    One consequence is that C++ is the only language I know with libraries that allow performing numerics with physical units safety without incurring significant runtime overhead – also compile time verification to avoid "volume plus area" type mistakes.

    So yes, generics are much less powerful. Solving tic tac toe at compile time however, doesn't really demonstrate why you'd want to pay the cost for the power.

  • TheJayMann (github)

    So... Have you even used Entity Framework before? Inheriting from DbContext not only is not a code smell, as far as I can tell it is the only way to actually use Entity Framework, as, to access the table types, you need to either define DbSet<T> typed properties on your DbContext derived type, or you need to override the OnModelCreating method, and call the modelBuilder.Entity<T>() method to enable the use of the Set<T>() method. Attempting to use the Set<T>() method without either defining a corresponding DbSet<T> property or calling modelBuilder.Entity<T>() in the OnModelCreating method will result in a runtime exception "System.InvalidOperationException: The entity type 'T' was not found. Ensure that the entity type has been added to the model."

    Most everything else in the article is on point, though there is a fairly narrow edge case where a generic repository type works well, such as when creating multiple CRUD pages for the multiple different entity types which would otherwise have the same code repeated, save for different entity types. But, even then, it really only makes sense within a single project, and not a system wide dependency.

  • (author) in reply to TheJayMann

    Admittedly, it's been a minute- at least in the versions I used, you didn't do anything like what you describe.

  • fanguad (unregistered) in reply to TheCPUWizard

    You've just provided a perfect example of why Generic are preferred by many. I don't want my data structures to be able to play tic tac toe.

  • Brian (unregistered) in reply to R3D3

    That was my experience as well. Coming from C++, it took me a while to wrap my head around C# generics, since they're evaluated at run-time instead of compile-time. A lot of my favorite C++ tricks just didn't work anymore, like creating type-specific instances of a template or even just using the compiler for type-checking.

  • (nodebb) in reply to Brian

    What kind of compiler type checking didn't work for you? I've only really used generics with Java, but there the whole point is to provide static type checking and safe automatic casting, where otherwise you'd be passing around bare Object instances, with no enforcement of type constraints.

  • (nodebb)

    If the template is "playing" Tic-Tac-Toe, it's basically just macros that generate the entire game tree. Which is only possible because Tic-Tac-Toe has a tiny game tree. Theoretically you could also do the same thing with chess, but you'd run out of disk space for the executable.

  • (nodebb)

    Any type substitution system which can't play basketball is inferior.

  • pudin9 (unregistered) in reply to TheJayMann

    You're right, here's what the documentation of DbSet <> says (https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext?view=efcore-5.0):

    "Typically you create a class that derives from DbContext and contains DbSet<TEntity> properties for each entity in the model."

  • DanK (unregistered) in reply to TheCPUWizard

    I think C++ causes permanent brain damage.

  • So is it... (unregistered)

    So is the real WTF the fact that everyone couldn't just use the class as intended and cope with the extra freedom of being able to specify a type in the method calls provided?

  • (nodebb)

    var carRepo = new Repository<Car>(); fooRepo.SaveEntity<Driver>(new Driver());

    Um, you realize you have two different variables here, Remy?

  • TheOldGuy (unregistered)

    I read all this and understood the words. Being that I dealt with programming with C, i probably would understand this reasonably well eventually. The issue for me is this is too far in "abstract theory" which is the far opposite end of the spectrum from where I am was as a programmer in C and Unix.

  • Sole Purpose Of Visit (unregistered) in reply to Ross_Presser

    I think all of us realised that.

    On a (mostly) daily post, it's reasonable for the reader to fill in the gaps. Took me about five seconds. YMMV.

  • Sole Purpose Of Visit (unregistered) in reply to TheOldGuy

    It's more "framework" than "abstract theory."

    I rather like the notion of Enterprise Framework, and one of my cow-orkers (out of a herd of five) has used it to good effect.

    But it doesn't take "abstract theory" to make you question the idiotic idea of applying generics to methods within a generic type. Or to despair at the consequent plethora of concrete types that are instantiated off that monstrosity.

    You live with the Framework, or you die with the Framework. In this case .. Are You Not Entertained?

  • (nodebb)

    I'm kind of curious to see the version history of this code. What would I find if I looked in trunk?

  • INVESTGENIX USA (unregistered)
    Comment held for moderation.
  • (nodebb)

    I think some people demonstrated a profound misunderstanding of templates vs generics. C++ (unmanaged) cannot have generics, definitely not the way they're done in .NET and probably not even the Java way. C# (the language, not .NET) and likely Java (again, the language, not JVM) could have supported templates, and they would, in some very narrow use cases, be slightly faster than generics; but generics provide many more benefits, and the performance improvements would be too insignificant and limited to too few use cases, to be justified. If you need to write something which is absolutely CPU-performance critical, you should use C++ or something similar, anyway; there is no way any managed language will ever match unmanaged performance. Also, some people said generics don't offer compile time type checking - what??!! Of course they do.

    TLDR, this pissing contest of templates vs generics is meaningless. These are 2 different technologies, in 2 separate ecosystems, aimed at different goals.

  • DanK (unregistered) in reply to Mr. TA

    Why would you need a managed environment for generics? The Java version of generics is just syntactic sugar that does not require anything new from the environment. I don't see why C++ could not do the same thing with pointers instead of handles.

    there is no way any managed language will ever match unmanaged performance

    You may want to think about that again. Managed environments know a lot more about the application than a compiler. Most projects do not use profile-guided optimization, but even if they did, a managed environment can profile the application in real-time and make better optimization decisions. GC can also be faster than manual memory management.

  • Paulina (unregistered) in reply to Watson

    I've tried to find the root. But somewhere my company migrated from svn to git and the old repo is locked away somewhere. All the employees who designed this are all gone. The apps still using this have been running for over 5 years. Currently we're luckily getting money to migrate these old framework apps to .net 5/6, so we're just starting to rewrite them. A lot of work, but better in the long term.

  • Programmer Bot 1-32612 (unregistered)

    So from this discussion we can conclude that Wargame's WOPR was written using C++ templates. No wonder it couldn't figure out how to beat the Russians at thermonuclear war.

  • David Mårtensson (unregistered) in reply to DanK

    Regarding performance of managed vs unmanaged I would say that a good enough developer would most likely always be able to beat the compiler and any runtime evaluation but as complexity grows it would be harder and harder to do and or most developers they just do not have the experience or deep understanding to beat the managed runtime, and any attempt would probably just add more bugs, extending development time so much that even that might spoil any gains while running the program ;)

  • (nodebb) in reply to DanK

    Unmanaged languages including C++ cannot have generics because the value can be of various sizes. If you put all the values to a heap and the generic type holds pointers to those, 1) you're wasting performance on pointer resolution, 2) you're spending basically twice the amount of memory. But most importantly, you cannot get any of the benefits of generics; since we're unmanaged, there are no type descriptors, attributes, etc. So generics in C++ would be heavier than templates (a con) and not any better. People realized this and went with the template approach.

    Addendum 2021-07-01 20:14: Re performance, in some cases managed frameworks can optimize some stuff away, but in a pedal to the metal scenario with heavy CPU workloads, there just isn't a way to optimize it away; unmanaged will be faster, period.

  • (nodebb) in reply to David Mårtensson

    Yes, and the bad developer who cannot optimize a complex unmanaged codebase will also likely mess up a managed codebase in other ways. For example, managed frameworks are not immune to memory leaks.

  • MaxiTB (unregistered)

    Oh boy, I think Remy is for sure not a .net developer and tries to translate Java Hibernate knowledge to EntityFramework - which is a huge reason why I get always my believe confirmed that "Java developers are worse C# developer than people that never code before" :-)

    Lets break it down, to clarify for all non .net developers how C# is layered.

    Since the beginning of .net the frame had one major advantage over Java, with System.Data.Common database classes were introduced with abstract database access, no matter the database in the background. Sure, those were not perfect, clunky to handle and you still need to implement a lot database specific functionality especially when it comes to functionality that is way more advanced and goes beyond simple CRUDL operations.

    So if you implement a Repository pattern, the correct starting point is System.Data.Common and perhaps use one of various mapper libraries to to the ORM.

    EntityFramework is way beyond of a simple ORM mapper, it implemented the Unit Of Work pattern. People aware of this pattern know, that it implements the repository pattern, object mapping, versionized schema migrations plus state tracking in a context. This has the major advantage that you don't need to worry about transactions, because the context is the transaction over multiple repositories - one of the major shortcomings of a pure repository pattern implementation.

    So the real WTF is that someone had the idea to implement a repository pattern over the unit of work pattern which implements the repository pattern for each database object. It's also very easy to spot in the given code: context.Set<T> is the repository pattern implementation.

    Worse of all, directly changing the state of entities is never a good idea, for that you have methods like Add<T>, Update<T> and Remove<T> in the context. Those synchronize according to the Unit of Work pattern changes over all repositories and ensure that correct state for navigation objects as well.

  • Alex (unregistered) in reply to MaxiTB

    The real WTF is that Microsoft used to recommend implementing a repository pattern over DbContext.

  • (nodebb) in reply to DanK

    Another consideration: .NET does genetics differently than Java and it my understanding is correct, the performance aspect is closer to that of templates than generics in Java. Since the framework creates special types for generics, it can actually pass the values around without boxing them which i think Java cannot do - it always boxes because the underlying JVM type just deals with objects. So, instead of complaining that tempest are better than generics, one should complain that Java generics have their disadvantages.

  • sh_code (unregistered) in reply to TheCPUWizard

    psst...

    1. ...i heard you like programming, but you don't like doing programming to do your programming, so I made a language for you so that you can do your programming via templating (which is essentially programming your programming to do the programming) instead of programming.

    2. Utopia achieved.

  • News Dekho (unregistered)
    Comment held for moderation.
  • Lars Høgedal (github) in reply to Remy Porter

    Thats gotta have been a pretty long minute. I made my first entity framewowrk implementation around 2012, and back then deriving from dbcontext was definately the only way to do an EF implementation.

  • JustARandomGuy (unregistered) in reply to Paulina

    Paulina, when i saw the code i thought we may actually be collegues XD This code seems copy/pasted from a project i'm currently working on!!

Leave a comment on “Repository, Man”

Log In or post as a guest

Replying to comment #529167:

« Return to Article