Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
ninjeff
Jan 19, 2004

Gul Banana posted:

presenting: casual basic. imagine this everyday scenario: you'd love to use Microsoft Visual Basic .NET but just cant bring yourself to reach for the shift key. if only it was Microsoft visual basic .NET. case-preserving case-insensitivity? there has to be a better way.

now there is a better way.


license: anybody can use it for anything

rejected! look at the inconsistent capitalisation of sub new/mybase.New

Adbot
ADBOT LOVES YOU

ninjeff
Jan 19, 2004

gently caress them posted:

I think stopping to take a break helped me get it. FIGURES.

code:
        Dim typeIDs = _
        (From I In context.trItems
        Join T In context.trTypes
        On I.trTypeID Equals T.trTypeID
        Select T).Distinct()
Time to test now.

I really need to nag work into getting me a linqpad license.

Change this to:
code:
Dim typeIDs = From i In context.trItems
              Join t In context.trTypes On i.trTypeID Equals t.trTypeID
              Select i.trTypeID, t.Category
              Distinct
and you will find a) the LINQ query easier to read and b) the generated SQL much faster.

ninjeff
Jan 19, 2004

RICHUNCLEPENNYBAGS posted:

OK, I'm feeling in a heretical mood, so I'm going to go ahead and bite on this: is it really morally superior to have a whole separate data layer that looks up an object by ID rather than to have context.SomeDbSet.Find(id)? What's it giving you?

Assuming this is for a model that doesn't consist only of single-table entities, one advantage is not having to write a litany of .Include(property) calls every time you want to get a complex object without triggering the N+1 select problem.

ninjeff
Jan 19, 2004

Mr Shiny Pants posted:

Another MVVM question:

I have my View and View Model setup. With help from you guys my NotifyPropertyChanged is working like it should and commands work as they should. My XAML is binded dynamically and I have almost no code in the code behind files.

So far so good you would say, but I have a hard time with the following:

Now where does the model come into play? I have a big class that represents my model data. It is a hierarchical structure of data that represents one work item in our business.

The 'model' in MVVM generally isn't a specific object as such, it's just the rest of your program not related to dealing with WPF.

Mr Shiny Pants posted:

The ViewModel has extraneous properties like currently selected item and the like, this is not "business data" so I get why business data is stored in the model.

But how do I update the model and make the viewmodel aware of the changes? Do I need to make InotifyPropertyChanged properties on the model?

This would just make the ViewModel a proxy for the model without the extraneous properties? It feels like DB -> DAL -> DTO -> ViewModel all over again :( Unpacking classes and repacking them again.

This does not seem right to me. Is there something I am missing?

In my experience the viewmodel is what's telling the model to change (in response to viewmodel property changes, commands, etc.), so it can update itself according to the results of the model changes. If this ends up making your viewmodels too complex then you can introduce controller classes to coordinate between the model and viewmodel, making a kind of MVCVM.

ninjeff
Jan 19, 2004

Looks like Hyprlinkr for MVC (which is good). Nice!

ninjeff
Jan 19, 2004

Inverness posted:

A small, irrelevant recommendation. For a using statement you can do something like:
C# code:
using (var r = new BinaryReader(File.OpenRead(FileName))) { ... }
Every well written reader/writer class is will dispose the underlying stream too.

This feature is actually the opposite of well-written, IMO; it prevents you from keeping the stream around for a while and disposing of it later (say you want to read all the data in the file with a StreamReader, and then append some more data with a StreamWriter). It also makes it hard to verify that you're not leaking anything - how many of these reader/writer classes actually document what they dispose of? If the caller is savvy enough to using the reader/writer, they'll know they need to using the stream too.

The BCL designers appear to agree - this StreamReader constructor overload was added in .NET 4.5. My thinking is that either rigorous ownership semantics weren't worked out in 1.0, or using was new enough that it wasn't clear how well developers were going to use it - see the 'dispose pattern' mess for another example of an attempt at safeguarding IDisposable that probably caused more harm than good.

There is one situation where I think readers/writers should act the way you describe: when created through a convenience constructor that takes e.g. a file path, and creates the stream itself. In this case the caller obviously has no way to dispose of the stream, so the reader/writer should do it.

ninjeff
Jan 19, 2004

TheBlackVegetable posted:

You'll need to block before exiting the application - I like to use the CancelKeyPress coupled with a WaitOne - hit Ctrl-C to close the application. This should let you see the sql call execute and any hit any exceptions.

This is probably it, chippy - your program is exiting because you're hitting the end of Main. My guess is that SqlConnection's constructor is the first operation expensive enough to cause a context switch that lets Main complete.

ninjeff
Jan 19, 2004

Gul Banana posted:

i wasn't very clear before due to phoneposting, but mr. shiny pants has it right. there's nothing wrong with "just some endpoints where you can get stuff over HTTP" though- the implication is that it then doesn't matter much what the Right Way is, because it's whatever you make up.

people sometimes talk about "levels" of REST these days, which are like
level 1 - you're using http methods and json
level 2 - the api is oriented around resources rather than calls
level 3 - client application state transitions via discovered hypermedia

each brings you closer to a model which is in theory highly scalable, evolvable, etc, but is not actually necessary, particularly if you have only a single client and server.

This is a pretty readable intro to the "levels" concept Gul Banana mentioned

ninjeff
Jan 19, 2004

The nullability thing seems like a good pragmatic solution to a problem that has been resisting perfect solutions for more than a decade (in this context) now! :thumbsup:

ninjeff
Jan 19, 2004

GrumpyDoctor posted:

code:
double[] x = { building.geoProperties.CoreArea + building.geoProperties.PerimeterArea };
Expression has been evaluated and has no value
res.Data["Total Area"] = new UmiDataSeries { Data = x };
{Mit.Umi.Core.UmiDataSeries}
    Data: {double[1]}
    Name: null
    Resolution: null
    Units: null
res.Data["Total Area"] = new UmiDataSeries { Data = { building.geoProperties.CoreArea + building.geoProperties.PerimeterArea } };
[don't wanna break the tables] threw an exception of type 'System.NullReferenceException'
what

This is not just happening in the Immediate window - the exception is thrown by my code. Seriously, what the hell is this?

edit: I made a simpler case

If you want to initialise IListProperty to an array then line 27 should be IListProperty = new [] { 1.0 }. If you want it to be some other collection type then you need to specify that. As-is, what you have there compiles to something like:
code:
var caseB = new IListMember();
caseB.IListProperty.Add(1.0);
You should be able to see why this throws a NullReferenceException :)

ninjeff
Jan 19, 2004

crashdome posted:

Ok I see you are logging in from a new device. We're going to text you a code or maybe an email. We can wait while you run to another device to check that code.... I hope you don't have alzheimers!

OK you got the code and you managed to enter it correctly. Great! Please wait while we forget what page you were on and redirect you back to the beginning. We'll probably ask you to login again.

Ok I see you are logging in from a new device in bed in the middle of the night and your two-week old baby has just fallen asleep. We've sent you an SMS! Now you must race against time to put your phone on silent before it makes a big-rear end sound and wakes up the whole family.

ninjeff
Jan 19, 2004

GrumpyDoctor posted:

I'm having a problem with Progress<T>. I've got something like this:
C# code:
var report = new Progress<int>(ticks => UpdateUIOrWhatever());

Parallel.ForEach(things, x =>
{
    DoLongRunningThing(x);
    report.Report(1);
});
What happens is that the first 20 or so reports pile up somewhere and then eventually go off all at once. After that, there's one after each long running thing completes (what I expected). Using debug stepping I can see that the calls to report.Report just vanish into the ether. Where are they going, and how can I get them to show up when I want them to?

Judging from http://referencesource.microsoft.com/#mscorlib/system/progress.cs, Progress<T> saves the SynchronizationContext it's created in and then posts every report back to that. You're seeing the Report calls "vanish" because they're going to another SynchonizationContext for it to handle whenever (not synchronously). If that SynchronizationContext is the WPF dispatcher or something similar, then it might still be dealing with your button click or whatever triggered this code before it gets around to handling any Reports.

If you want an IProgress<T> that acts exactly how you want it to, you could just implement the interface yourself - you'll then be responsible for handling concurrency. Keep in mind that if you're updating a single-threaded UI, you're going to have to either learn to deal with updates "vanishing" into a queue or synchronously update it (with e.g. Dispatcher.Invoke), and the latter is going to kill the performance benefit of Parallel.ForEach.

ninjeff
Jan 19, 2004

GrumpyDoctor posted:

See, that makes total sense in theory, but I can't figure out what's actually causing the holdup on the original SynchronizationContext. To explain more, there's an additional wrinkle: The thread calling Parallel.ForEach isn't the UI thread, but a worker thread spawned by the UI thread with Task.Run. Here's what it looks like:
code:
                               long-running task
                              /
UI thread - background thread  - long-running task
                              \
                               long-running task
My understanding of the way this works is that each long-running task will post its updates back to the default SynchronizationContext. The background thread is then responsible for updating the UI. (It does this using Dispatcher.Invoke.) I can see where the queue backlog is, but I don't understand why it's happening, because the delay is several seconds long, and the UI is totally responsive the whole time. Is the default SynchronizationContext not what I want here? Which one should I use instead?

OK, that's a bit more strange. My only thought is that perhaps the thread pool's getting saturated - IIRC it can only spin up one new thread per second by default, so if all of the current threads are busy doing your Parallel.ForEach work then the Report calls might have to wait a little while to get any time. In this case it might actually be better to create the Progress<T> on the Dispatcher, as that's not going to be tied down by thread pool work. Alternatively, you could set the MaxDegreeOfParallelism on your ForEach to one less than the number of cores to effectively reserve a thread for other work, but that'll have a pretty significant effect on your throughput.

ninjeff
Jan 19, 2004

22 Eargesplitten posted:

If I type in something that's part of a built-in method and then type something else like "." it auto-completes that method. How do I get it to not do that? I'd rather have it set to where I hit a button to confirm I want that completion.

press escape

ninjeff
Jan 19, 2004


Looks like "race" was find-replaced. I wonder what the story there is.

ninjeff
Jan 19, 2004

xgalaxy posted:

Hahah. Wow that guy just completely went against the wishes of everyone there and merged the commit anyway.

There was only one other person there!

ninjeff
Jan 19, 2004

raminasi posted:

That is a very odd disclaimer for them to have added, because all the IDictionary and IDictionary<> implementations simply forward through to the thread-safe methods.

You're equivocating on the multiple meanings of thread safety. Individual methods being thread-safe (can't fail due to concurrency) doesn't mean that you can use them together in a thread-safe (useful for anything without having to add your own synchronization) way. Achieving the functionality of ConcurrentDictionary's GetOrAdd and TryRemove methods through the IDictionary interface would mean adding your own synchronization, and if you're going to do that then you might as well just use Dictionary instead - it'll perform better.

ninjeff
Jan 19, 2004

chippy posted:

I'm just spitballing here, but what about :

code:
IQueryable<Recipe> query = db.Recipes
	.Where(r => (String.IsNullOrWhitespace(searchRecipe.Name) || r.Name == searchRecipe.Name) || (String.IsNullOrWhitespace(searchRecipe.Hops) || r.Hops == searchRecipe.Hops));
and so on, for all the clauses. Would the short circuiting behaviour stop the other clauses being checked if the strings were empty maybe? Or is this mental?

If this is actually going to a database and not just LINQ to Objects, you're going to end up sending the String.IsNullOrWhitespace calls to the database too - this will give you a pretty bad execution plan and might not even be supported by the LINQ provider to begin with. You're going to want to use something like PredicateBuilder that Bognar mentioned or write some expression composition yourself.

ninjeff
Jan 19, 2004

Sedro posted:

Are you sure there is a problem? The nulls will disappear from the expression e.g. WHERE recipes.name = 'name' OR false OR false OR recipes.yeast = 'yeast'

You're calling String.IsNullOrWhitespace on the query parameter, not on the column. The query optimizer will reduce the expression WHERE true OR expr

The String.IsNullOrWhitespace call isn't necessarily executed by the LINQ provider, which just receives it as an arbitrary expression. EF might understand that 'expression of a method call to String.IsNullOrWhitepsace on a known value' needs to be precalculated and do so, but if it doesn't then you'll instead get something like WHERE @q_Name NOT LIKE '' OR recipes.Name = @q_Name, which will optimize poorly.

Adbot
ADBOT LOVES YOU

ninjeff
Jan 19, 2004

Bognar posted:

Execution plan optimizers are very smart and this is low hanging fruit. Most optimizers will collapse static expressions like this before execution time resulting in either a simple filter on Name, or an elided where clause altogether.

All I can offer is this appeal to authority: http://use-the-index-luke.com/sql/where-clause/obfuscation/smart-logic. The summary is that yes, databases can optimize this but you'll kill execution plan caching.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply