|
Ignore the above. I found the culprit. Typically, the previous coder had no idea how async code works:code:
|
# ? Jan 21, 2020 22:43 |
|
|
# ? Jun 8, 2024 08:06 |
|
a hot gujju bhabhi posted:As you can see, this is not going to do what the comment claims at all. Oh! It looks to me like it will do what the comment claims... Could you talk through your reasoning? What I think this code will do: starting at time=0, and thereafter once a second, it will check whether BackgroundRefreshInProgress is true or whether 10 once-per-second retries are up. If it is true and retries aren't up, it will wait a second and try again. The Scope.Dispose() call will either run on the calling thread and propagate exceptions (if done at time=0) or on a background thread and the exception will be unhandled. (Uncertain: I don't know if this overload of Task.Run takes a void-returning async lambda - in which case I think any unhandled exception will get passed to the execution-context exception handler - or if it takes a Task-returning async lambda, in which case the exception will be silently ignored.)
|
# ? Jan 22, 2020 20:04 |
|
ljw1004 posted:Oh! It looks to me like it will do what the comment claims... Could you talk through your reasoning? Not the op, but what I think happens is: the runtime calls dispose right before garbage collection. It doesn’t know to wait for the thread to complete. Race condition ensues, program blows up.
|
# ? Jan 22, 2020 20:51 |
|
In general, the pattern of Dispose being called from the finalizer before GC is such a rare scenario that it would be better if everyone pretended it did not exist - it confuses people more often than not. Yes, for releasing some unmanaged resources it is what needs to happen but if we are talking of managed resources, you should only ever be calling Dispose() explicitly (or via using block) and there should not be any finalizer defined. We can be pretty sure that Dispose() is being called here intentionally and not by a finalizer, as the Scope variable sounds like a data context of some sort (a managed object, not an unmanaged resource like a file on disk or some raw handle). While the code does not impress in some ways, I would also concur that the implementation seems to match the comment. It just starts a new task with a delay and calls itself again a maximum of 10 times or until BackgroundRefreshInProgress is false, after which it really disposes the Scope.
|
# ? Jan 22, 2020 21:26 |
|
Maybe, but the op mentioned in this, or another thread that his service was crashing intermittently with an exception related to dispose, and he said he tracked it down to this method. My guess is some kind of race condition.
|
# ? Jan 22, 2020 21:42 |
|
Hmm maybe there's more going on than I thought. After looking at it again I can see what you guys are saying, but making that part synchronous so that disposal had to wait for the CacheService to be finished fixed the problem. I'll do my best to explain what this thing is doing, I'd really like to understand why it's breaking, seems like my initial thought was wrong. The class is called UnitOfWork and it extends a base class called ServiceScope. The constructor creates a new Autofac container with a bunch of registrations set to the Lifetime scope. The constructor then immediately calls "BeginLifetimeScope". Among those registrations is an Entity Framework context. When I first came across that code, I read the comment as "wait for the CacheService to finish before disposing this class" so I thought the code was wrong, but I see what you guys are saying now. But clearly something about this logic is causing the DbContext to be disposed before it should be, anyone have any ideas what it could be? Possibly worth noting that the Dispose method is not called explicitly, but the instance is inside a using statement. code:
putin is a cunt fucked around with this message at 22:02 on Jan 22, 2020 |
# ? Jan 22, 2020 21:59 |
|
The call to UnitOfWork.Dispose() will immediately return while the delay will continue asynchronously. The Dispose call returning immediately and allowing the calling code to continue could be the issue, if running synchronously and waiting for Dispose to complete fixed the problem you were having. *Edit: Your coding horror post said maybe you were the horror, however I agree with ljw1004 about the uncertainty of the Task.Run here. What seems very very likely to me (and a quick test appears to confirm it) is that any exceptions thrown by DoDispose will get silently eaten by the anonymous Task returned by Task.Run. Maybe it's guaranteed that Scope.Dispose will never, ever throw an exception...but that's a pretty risky assumption to make from a completely different classes dispose function. While this code may do what the comment indicates, it's not great code either. Faldoncow fucked around with this message at 22:37 on Jan 22, 2020 |
# ? Jan 22, 2020 22:16 |
|
a hot gujju bhabhi posted:Hmm maybe there's more going on than I thought. After looking at it again I can see what you guys are saying, but making that part synchronous so that disposal had to wait for the CacheService to be finished fixed the problem. I wonder if the call to Dispose() fails when run on a different thread due to a race condition somewhere?
|
# ? Jan 22, 2020 23:18 |
|
Is Scope/CacheService() shared between multiple instances of UnitOfWork classes by any chance? While calling subsequent Dispose() should be a no-op, I have yet to see implementation of it that's thread safe. And EF Context is definitely not thread safe by any chance. So if my first assumption holds, it could be possible to: 1. First UnitOfWork does something. 2. First UnitOfWork tries to Dispose, but CacheService().BackgroundRefreshInProgress is true. 3. Second UnitOfWork does something. 4a. Second UnitOfWork tries to Dispose and CacheService().BackgroundRefreshInProgress is false. 4b. First UnitOfWork retries to Dispose at the same time, on different thread. 5. EF craps its pants.
|
# ? Jan 22, 2020 23:29 |
|
Faldoncow posted:The call to UnitOfWork.Dispose() will immediately return while the delay will continue asynchronously. The Dispose call returning immediately and allowing the calling code to continue could be the issue, if running synchronously and waiting for Dispose to complete fixed the problem you were having. Yeah I thought (maybe incorrectly) that if the Dispose method completes then the runtime will immediately move on to disposing the resources belonging to the UnitOfWork, including the Autofac scope that was created in the constructor and is supposed to be (per the comment) disposed after a delay. This is where I think maybe I'm wrong, from what people are saying here?
|
# ? Jan 22, 2020 23:42 |
|
I take it all back, it seems like the error is still there somewhere. gently caress my life. This is seriously making me miserable.
|
# ? Jan 23, 2020 00:06 |
|
Does your UoW inject an EF context which has a different lifecycle? Calling Dispose in your UoW should not manually dispose the EF Context, it should live inside the same scope as the EF Context, and Autofac handles disposing both (or your UoW doesn't dipose EF, either or).
|
# ? Jan 23, 2020 15:33 |
|
Entity Framework. Never.
|
# ? Jan 23, 2020 21:42 |
|
MisterZimbu posted:Entity Framework. Never. I've used Entity Framework in heaps of projects over the years without issue. This isn't an Entity Framework issue.
|
# ? Jan 23, 2020 23:22 |
|
this product is the first time i've had the pleasure of working with ef core. i've been bitten by enough weird bugs from both ef and the way we use it that i'd be extremely cautious about using it in the future
|
# ? Jan 24, 2020 01:41 |
|
redleader posted:this product is the first time i've had the pleasure of working with ef core. i've been bitten by enough weird bugs from both ef and the way we use it that i'd be extremely cautious about using it in the future What are the EF bugs you've been bitten by in EF Core?
|
# ? Jan 24, 2020 04:40 |
|
Well, it depends on the usage but I can certainly agree that horrible experiences with EF are possible. The main issues with EF (Core) that I have encountered are: 1. Migrations sometimes glitch out and EF thinks you need to apply some nonsense migration that is a no-op at best but can sometimes even be destructive. 2. LINQ->SQL transformations are extremely limited once you move on from basic "SELECT X FROM Y WHERE Z" types of queries. 3. No built-in bulk operation support. These are the big pain points for me but life with EF is certainly better than without EF. However, I am careful to only use the "good parts" of EF. For example, I would never touch the inheritance hierarchy modeling functionality, I treat lazy loading as cancer to be rooted out, I keep any writable EF object lifetimes constrained to a single C# method (any EF objects returned are strictly read-only and never used for pushing data to the database). It took me years to learn the right patterns and they are not really documented anywhere - if you read guides, they just tell you what features do, rarely when it is appropriate to use them (or even more importantly, to avoid them). Given that, I would say that you need to know how to use it and you'll be fine. Use it as a minimal C#<->SQL translation layer and you'll be fine. But if you just take all the documented features and apply them in a spray-and-pray pattern in your business logic, you will suffer greatly.
|
# ? Jan 25, 2020 08:26 |
|
EssOEss posted:Well, it depends on the usage but I can certainly agree that horrible experiences with EF are possible. The main issues with EF (Core) that I have encountered are: Exactly, it's just about knowing what you're doing and designing your code appropriately. Lazy loading should never be a problem because you should really be projecting your queries to domain models at the outset. If you're gonna do an update, use a dto to represent the change, fetch the object and update and save it in the same method as you said. Look I agree that getting to know EF well is hard work, but the benefits it brings are immense.
|
# ? Jan 25, 2020 08:33 |
|
EssOEss posted:
So, why bother with EF at all. You could just use something like Dapper with a simple DB Migration tool like DBUp or even homegrown. You don't get automatic migrations from your domain objects, but I always found that clunky and annoying anyway - like I was trying to guide it to write the DDL SQL I could just write myself, cleaner. I've also used the Dapper Contrib stuff for when I'm feeling lazy and want something to generate INSERT/UPDATE statements for simple domain objects.
|
# ? Jan 25, 2020 15:36 |
|
Communicating over a network, communicating with a database using an agreed-upon protocol, deserializing data retrieved from a database, and serializing data that you want a database to write are all solved problems. Managing a database schema, managing data object lifecycles during application execution, scoping transactions, writing queries, and migrating data are problems that have solutions. These things are subtly different. Micro-ORMs like Dapper only solve the former while traditional, thicker ORMs like EF claim to also be able to solve the latter. Often they're able to, until they can't. Complexity is inevitable if your application is going to do anything useful, and at some point you're going to have to make a change to your software that reveals someone made a bad assumption somewhere. That's how you get into poo poo like this: a hot gujju bhabhi posted:These days I'm working on a large repository of .NET Framework horseshit and I'm having some trouble with Entity Framework because the people who originally built this out clearly didn't know how to use it. I have a Windows service, with various unnecessary layers of complexity behind it, and something in there is causing the service to "randomly" crash. The people that wrote that could just suck, or maybe they did need to add complexity because the business requirements demanded it but EF didn't leave them any room to manage that complexity in a more sane manner. EssOEss posted:Well, it depends on the usage but I can certainly agree that horrible experiences with EF are possible. The main issues with EF (Core) that I have encountered are: a hot gujju bhabhi posted:Exactly, it's just about knowing what you're doing and designing your code appropriately. Lazy loading should never be a problem because you should really be projecting your queries to domain models at the outset. If you're gonna do an update, use a dto to represent the change, fetch the object and update and save it in the same method as you said. If EF brings all these footguns if it's used beyond performing basic queries or simple data writes, why not just write the SQL directly? I agree that manually mapping data between something like ADO.NET and POCOs is a huge pain, but Dapper solves that problem and seems like a better fit than what you're using EF for. ThePeavstenator fucked around with this message at 22:47 on Jan 25, 2020 |
# ? Jan 25, 2020 22:45 |
|
a hot gujju bhabhi posted:What are the EF bugs you've been bitten by in EF Core? it's not a bug (because it's documented), but the most egregious foogun i've found with ef core is mentioned only in a sidebar: https://docs.microsoft.com/en-us/ef/core/querying/related-data posted:Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded. in other words, ef does some magical bullshit to map up child and child-of-child properties invisibly, that can break when you remove an earlier and apparently unrelated db call, or even reorder some operations. this happens even when eager loading, when you think you've got all the Includes().ThenIncludes() that you need other issues i have with it have been called out by other posters some of my problems could be described as us doing it wrong... but ms offers no guidance as to how and when to use ef and when to look elsewhere (which is a pattern i've seen with every other ms product i guess)
|
# ? Jan 26, 2020 06:07 |
|
If you're using .Includes and ESPECIALLY .ThenIncludes then you are doing it wrong. And yes, the fact this isn't better understood is definitely a Microsoft failing, but it doesn't make EF any less poo poo when you use it correctly. To expand: EF is a DAL, but too many people try to write a DAL of their own using EF as the communication mechanism. EF is a strongly typed representation of your database and you should take that literally (never pull out entities as they are, pull them out as domain models using projections) so that you don't wind up passing database records around. Database -> Domain logic is a domain barrier and you should only cross it using intermediate DTO objects, not actual database records. putin is a cunt fucked around with this message at 08:51 on Jan 26, 2020 |
# ? Jan 26, 2020 08:47 |
|
on that note, any ways to make generating and mapping dtos from aspnet request dto -> domain model -> database dto and vice versa? it is deeply, deeply tedious, especially when creating multiply nested objects
|
# ? Jan 26, 2020 09:32 |
|
ThePeavstenator posted:If EF brings all these footguns if it's used beyond performing basic queries or simple data writes, why not just write the SQL directly? I agree that manually mapping data between something like ADO.NET and POCOs is a huge pain, but Dapper solves that problem and seems like a better fit than what you're using EF for. That's a fair question. I have used Dapper for a while, as well, and in the end found EF still more productive to work with. One comes with a bag of footguns, the other just comes with not quite enough substance, I feel. On the balance, EF won out for me. I wish there were some middle ground option between them but it seems that libraries often come in "bare minimum" and "all the trinkets in the world" variants - as soon as the authors start going down the path of adding more features, they tend not to be able to stop.
|
# ? Jan 26, 2020 09:43 |
|
a hot gujju bhabhi posted:If you're using .Includes and ESPECIALLY .ThenIncludes then you are doing it wrong. And yes, the fact this isn't better understood is definitely a Microsoft failing, but it doesn't make EF any less poo poo when you use it correctly. Out of interest, doing things this way, how do you avoid 1/3rd of the codebase being overlapping model classes and their respective mappings?
|
# ? Jan 26, 2020 11:45 |
|
In the larger codebases where I worked, the initial "eww, do I really need to just make two very similar looking objects" feelings were quite quickly replaced by "phew, thank god I did not try using the same object for both of these layers". For trivial cases, the duplication might seem a bit time-wasting but once you get into more complex scenarios, it begins to pay off. Just accept the fact that the trivial objects will often be just very similar (or sometimes even equal) classes on multiple layers. The price has always ended up worth paying in my experience. Yeah, you might have 1/3 of your codebase filled with this stuff in some types of apps but if your app is data-operation-heavy then "spending" your code on the classes dealing with data is fine.
|
# ? Jan 26, 2020 13:58 |
|
I have what I feel is a weird and highly specific question: I am looking for a .NET Lua implementation/binding but one that specifically supports setfenv() and friends. Every library I've seen didn't bother implementing those functions because, roughly speaking, "it's hard" (assuming they didn't just do about two thirds of the built-in functions and then get bored, which seems the most common). Does anyone here know of such a thing? I very much do not want to have to write my own wrapper around the C API if I can get away with it. For the sake of argument let's say performance is irrelevant.
|
# ? Jan 26, 2020 14:26 |
|
EssOEss posted:In the larger codebases where I worked, the initial "eww, do I really need to just make two very similar looking objects" feelings were quite quickly replaced by "phew, thank god I did not try using the same object for both of these layers". Anyone that has ever worked on a codebase of any significant size and age realizes strict adherence to DRY typically causes more problems than it helps. Same with domain -> dto -> model mapping. It's tedious, but future-you will be relieved that changing a domain object doesn't require versioning your API or changing tons of code upstream. Also, as much as I love Jimmy, AutoMapper is the devil.
|
# ? Jan 26, 2020 16:12 |
|
a hot gujju bhabhi posted:To expand: EF is a DAL, but too many people try to write a DAL of their own using EF as the communication mechanism. I contend that you should do that. EF is a database communication tool. Your application shouldn't know or care that the data is being persisted in a SQL database via EF. Your application should depend on an abstraction that allows you to persist data. The tool used to persist data and the place the data is persisted should be completely irrelevant to the application. I've seen this come in handy when making the switch from monoliths to microservices, for example. Someone wrote a new implementation of the data access interfaces that used REST API calls to hit appropriate REST endpoints, and the core application was completely unperturbed that the data was going to and coming from a REST endpoint instead of directly from a SQL database. If EF code had been sprinkled willy-nilly throughout the application instead of nicely abstracted and isolated, replacing it would have been a huge effort bordering on total rewrite.
|
# ? Jan 26, 2020 16:30 |
|
EssOEss posted:In the larger codebases where I worked, the initial "eww, do I really need to just make two very similar looking objects" feelings were quite quickly replaced by "phew, thank god I did not try using the same object for both of these layers". For trivial cases, the duplication might seem a bit time-wasting but once you get into more complex scenarios, it begins to pay off. Just accept the fact that the trivial objects will often be just very similar (or sometimes even equal) classes on multiple layers. The price has always ended up worth paying in my experience. Yeah, you might have 1/3 of your codebase filled with this stuff in some types of apps but if your app is data-operation-heavy then "spending" your code on the classes dealing with data is fine. I was hoping there was one weird trick Jon Skeet doesn't want you to know. I totally agree with "don't re-use the model" by the way. When it comes up at work I cite the security exploits you get when someone model binds their ASP.NET action methods to the EF code-generated model classes, thankfully people don't tend to contest anything that might result in a GDPR gently caress up.
|
# ? Jan 26, 2020 17:32 |
|
redleader posted:on that note, any ways to make generating and mapping dtos from aspnet request dto -> domain model -> database dto and vice versa? it is deeply, deeply tedious, especially when creating multiply nested objects On the way out (from db entity to domain model), it’s pretty straightforward (because you’re creating new objects), you can use a mapping tool like AutoMapper or ValueInjecter and as long as you name and type the properties correctly it handles nested objects adequately. On the way back in, e.g. when saving a record (from domain model to db entity), this isn’t trivial (because you’re updating existing objects). You’re actually pulling up the db entity, copying values from the domain model, and automatic mappers don’t handle nested records well. Each child record may be new, changed, or missing (deleted), and you’ll need to tell EF to insert, update, or delete a child row in each case. I wrote a generic way to automate this into a one-liner years ago, something like UpdateManyToMany(domainModel.ChildList, dbEntity.ChildList), I should really publish the code in a blog post someday. Edit: And you’re right, there are actually 3 sets of classes, the db entities and domain models (as mentioned above), and then the UI-specific classes. It’s a lot of classes but after many years of figuring out what parts of EF to use/avoid, this is what I’ve settled on. epswing fucked around with this message at 20:20 on Jan 26, 2020 |
# ? Jan 26, 2020 20:10 |
|
power crystals posted:I have what I feel is a weird and highly specific question: I am looking for a .NET Lua implementation/binding but one that specifically supports setfenv() and friends. https://github.com/Myndale/KopiLua It was encouraged to check the forks because it's not an ambitious project with super support. It's kind of off-topic, but what the hell does setfenv do? I read it up and was really puzzled about it and kind of scared that it was some strange way of push/popping global variable state between calls or something.
|
# ? Jan 27, 2020 18:45 |
|
Well I guess a C# port of the C API at least saves me having to do that myself even if I’d have preferred something slightly higher level. And you aren’t far off. Basically, setfenv lets you swap out the _G global table when you call into another file. You can use this to prepopulate globals on the way in as a method of passing parameters, or read the file’s globals after it’s done as a way to get return values since lua has nothing approximating interfaces or a way to define an entry point in a file that you can call as a function, it just starts at character 0. You can also do setfenv(1, var) to swap out your own global table. I have yet to figure out why you’d ever want to do that, but you can.
|
# ? Jan 27, 2020 21:13 |
|
When I was looking at Lua/C# interop a bit ago I came across https://github.com/moonsharp-devs/moonsharp/ It's not really a Lua wrapper so it's not exactly what you're looking for, but it seemed intriguing to me at the time...I didn't actually get to use it, and I didn't see many opinions on it out there. But one day I'll give it a shot
|
# ? Jan 28, 2020 02:47 |
|
New Yorp New Yorp posted:I contend that you should do that. EF is a database communication tool. Your application shouldn't know or care that the data is being persisted in a SQL database via EF. Your application should depend on an abstraction that allows you to persist data. The tool used to persist data and the place the data is persisted should be completely irrelevant to the application. My argument is that you should isolate all of that code to your domain layer which will serve as an internal API of sorts, and your EF implementation of that interface is just one of many possible implementations you may eventually end up writing. Which I think you agree with and I've just not explained properly what I mean. What I'm arguing against is this model: code:
code:
|
# ? Jan 28, 2020 03:38 |
|
bobthenameless posted:When I was looking at Lua/C# interop a bit ago I came across https://github.com/moonsharp-devs/moonsharp/ Moonsharp is actually what I started with. It does not support setfenv (it also doesn't implement table.maxn somehow??) but it's otherwise gotten me to where I've been able to get most of what I want done by intercepting script loads and editing the contents. If you don't have my specific requirements it's actually pretty solid and I'd recommend it in general. power crystals fucked around with this message at 04:33 on Jan 28, 2020 |
# ? Jan 28, 2020 04:29 |
|
a hot gujju bhabhi posted:My argument is that you should isolate all of that code to your domain layer which will serve as an internal API of sorts, and your EF implementation of that interface is just one of many possible implementations you may eventually end up writing. Which I think you agree with and I've just not explained properly what I mean. What I'm arguing against is this model: I want data access logic totally isolated behind bespoke, domain-specific interfaces that can be mocked for testing and swapped to alternate implementations without having any impact on consuming code other than changing the concrete implementation that's passed in. Whether you call that a repository layer or a domain layer is really just semantics. If you have separate domain and repository layers where the domain layer is nothing more than a thin wrapper that forwards calls to a repository and returns results, yeah, sure. Eliminate a layer. If your domain layer is doing more than that, the repository should remain separate.
|
# ? Jan 28, 2020 06:10 |
|
Is there a Visual Studio tool to list the target frameworks of all projects in a solution?
|
# ? Jan 28, 2020 12:24 |
|
Boz0r posted:Is there a Visual Studio tool to list the target frameworks of all projects in a solution? Boz0r posted:Is there an easy way to see the target frameworks of all projects in a solution in Visual Studio? SirViver posted:Don't know of any built-in way, but you can use the Target Framework Migrator extension to get a quick overview.
|
# ? Jan 28, 2020 13:46 |
|
|
# ? Jun 8, 2024 08:06 |
|
Woops, sorry about that. I forgot I already asked.
|
# ? Jan 28, 2020 15:18 |