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
Captain Capacitor
Jan 21, 2008

The code you say?
For anyone working on .NET / WebAPI Projects I highly suggest trying out Glimpse. It's like the Chrome DevTools but with more insight into your code.

Adbot
ADBOT LOVES YOU

RICHUNCLEPENNYBAGS
Dec 21, 2010

The Wizard of Poz posted:

I also have a more general question around dependency injection. I have a controller action that looks like this:

code:
public class CoursesController : BaseController
{
    // GET: Course
    public ActionResult Details(int id, IOnlineEnrolmentManager manager)
    {
        Course course = manager.GetCourseById(id);

        return View("Details", course);
    }
}
In my actual project, the IOnlineEnrolmentManager will be implemented by a concrete class called OnlineEnrolmentManager. The interface is then re-implemented by a concrete class called MockManager in my test project. Because the accepted parameter is an interface rather than a concrete class, if I place my cursor on "GetCourseById(id)" and hit F12, I get take to the signature for that method in the interface class. If I wasn't supporting dependency injection I could just make the parameter a concrete type and then hitting F12 would take me to the actual implementation of the method. I know this is probably wishful thinking, but is there a way I can structure this so I can have the best of both worlds?

ReSharper supports "go to implementation" (I think this is ReSharper and not Visual Studio anyway), and if you've got multiple implementations it'll ask which one.

Bognar posted:

I don't have much time at the moment to elaborate, but I will say I strongly disagree with the general patterns described here. If you need a context, then instantiate one - don't keep the same one around for the lifetime of a request. Due to the way EF handles object caching, strange and unexpected things can happen. Similarly, you shouldn't just automatically set up a transaction per request. Even if you ignore the performance concerns, you still should reason about which requests actually require a transaction and only use one where it's necessary.

I'll elaborate more on this tonight when I have a bit more time.

EF does a transaction every time you call SaveChanges, doesn't it? Anyway, if you're running into problems with object caching I think you're doing some strange things in a single request. I don't think performance concerns are seriously worth worrying about unless you're doing a bulk insert of thousands of records -- in which case more contexts will help but you'll still have serious performance issues with EF.

RICHUNCLEPENNYBAGS fucked around with this message at 23:57 on Apr 27, 2015

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

RICHUNCLEPENNYBAGS posted:

ReSharper supports "go to implementation" (I think this is ReSharper and not Visual Studio anyway), and if you've got multiple implementations it'll ask which one.

Thanks guys for the ReSharper suggestion - I'll give their free trial a shot and see how I go.

Edit: Already super-impressed, lots of cool stuff in this add-on. Thanks again.

putin is a cunt fucked around with this message at 05:25 on Apr 28, 2015

chippy
Aug 16, 2006

OK I DON'T GET IT
Does anyone know why Visual Studio would do this?



I'm referring to the first incidence of panelProducts being highlighted like that. It's a local variable, passed in to the Sub as a parameter, and that's the first time it's references in the method. At first I thought I must have accidentally clashed with a class name or something, but as you can see, subsequent references aren't highlighted, and it does it no matter what I call it.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Funking Giblet posted:

I don't use EF, but NHibernate, which will always create a transaction no matter what, and it's bad for performance to not handle it yourself as it will create one per modification, so you might get a few transactions per action.

Ah, I can't say much for NHibernate - most of the advice I was giving was EF specific.

RICHUNCLEPENNYBAGS posted:

EF does a transaction every time you call SaveChanges, doesn't it?

It does, which is why it's very likely unnecessary for you to start one for each request.

RICHUNCLEPENNYBAGS posted:

Anyway, if you're running into problems with object caching I think you're doing some strange things in a single request.

It doesn't have to be strange, or even complicated. This example is inspired by something we ran into trying to do one context per request.

Lets say you have these models:
C# code:
public class User
{
    public int Id { get; set; }
    public int Name { get; set; }
}

public class Butt
{
    public int Id { get; set; }
    public bool IsGassy { get; set; }
    public User User { get; set; }
    public List<Fart> Farts { get; set; }
}

public class Fart
{
    public int Id { get; set; }
    public double SmellFactor { get; set; }
    public User User { get; set; }
}
The requirement is we need to be able to get a Butt and display its User's name and whether it's gassy. Somewhere in a service, you might have:

C# code:
public Butt GetButt(int id)
{
    return _context.Butts.Include(b => b.Users).FirstOrDefault(b => b.Id == id);
}
New requirement: in a different method, for a given butt you need to get the farts if it's gassy.

C# code:
public List<Fart> GetFarts(int buttId)
{
    var butt = GetButt(buttId);
    if (butt == null || !butt.IsGassy)
        return null;

    return _context.Farts.Where(f => f.Butt.Id == buttId).ToList();
}
Weeks pass and GetFarts is used across the codebase. Naturally, users want to know who dealt it, so in the UI somewhere mid-level developer Susie writes:

C# code:
    var farts = GetFarts(buttId);
    var user = farts.First().User;
    NameAndShame(user);
Through some analytics and user feedback, the manager realizes that users don't care about butts or gassiness, they just care about who farted. Little junior developer Johnny is tasked with deleting that page. While doing so, he realizes that GetButt can be optimized since the user isn't being displayed anymore.

C# code:
public Butt GetButt(int id)
{
    //return _context.Butts.Include(b => b.Users).FirstOrDefault(b => b.Id == id);
    return _context.Butts.FirstOrDefault(b => b.Id == id);
}
A few days pass until you get a bug report from a user. One of your pages isn't loading correctly and now users can't name and shame gassy people. The developer tasked with fixing it looks at the code and wonders how it ever worked in the first place, fixes it, then goes around talking about Susie behind her back.

What happened was that when Susie called GetFarts() and got the user to name and shame them, the user was already loaded in the context due to the call in GetButts(). Entity Framework automatically saw that the Farts UserId match the loaded User, so it automatically wired them up. It tries to connect the object graph to what's already loaded.
When Johnny removed the User from GetButt(), it affected one tiny far away section of code in non-obvious ways. It's hard to catch because it's hard to know what's already been loaded into the context or what callers are expecting to be loaded into the context.

You could say the root of the problem was bad developers not being careful, and to some extent that's true, but this was just a simple example. Add a few developers to a non-trivial project and tons of code can be accidentally written that is dependent on previous queries. Now it's a mine-field if you try to optimize queries by removing unnecessary includes, because you can't just test where that query is used, you have to test every thing that happens after that query is used in each request.

Another thing that makes this particularly hard to protect against is that Includes are one of the hardest things to unit test. EF's in-memory database in the next version may make this easier, but as of now there's no great way to test object caching and includes without touching the database.

I've harped on the Include aspect of object caching, but there's another slightly less disruptive issue. If you query the database and load a value into EF, something changes in the database, then you re-query the database with the same context, EF will NOT overwrite your previous values with the new changed values from the database. It will look at the Id, see that the object is already loaded, then ignore all the new values. This is not as big of an issue with web requests where the context lifetime should be short, but it is definitely a problem if you have anything with a long-running context.

In all, it's easier to just instantiate the context where you need it. You gain greater control over the semantics of how and when a context should be opened, and you don't run into nasty object caching issues.

Mellow_
Sep 13, 2010

:frog:
This might be a bit of a long shot, but has anyone here worked with DbGeomatry, specifically the functions that create shapes from WKT. I'm wanting to create a point with WKT from user input lat/long, but the values have to be transformed to represent a datum that I am unfamiliar with.

Anyone have any experience with transforming lat/long to WGS84 in a .Net language?

Funking Giblet
Jun 28, 2004

Jiglightful!

Bognar posted:

Ah, I can't say much for NHibernate - most of the advice I was giving was EF specific.


It does, which is why it's very likely unnecessary for you to start one for each request.


It doesn't have to be strange, or even complicated. This example is inspired by something we ran into trying to do one context per request.

Lets say you have these models:
C# code:
public class User
{
    public int Id { get; set; }
    public int Name { get; set; }
}

public class Butt
{
    public int Id { get; set; }
    public bool IsGassy { get; set; }
    public User User { get; set; }
    public List<Fart> Farts { get; set; }
}

public class Fart
{
    public int Id { get; set; }
    public double SmellFactor { get; set; }
    public User User { get; set; }
}
The requirement is we need to be able to get a Butt and display its User's name and whether it's gassy. Somewhere in a service, you might have:

C# code:
public Butt GetButt(int id)
{
    return _context.Butts.Include(b => b.Users).FirstOrDefault(b => b.Id == id);
}
New requirement: in a different method, for a given butt you need to get the farts if it's gassy.

C# code:
public List<Fart> GetFarts(int buttId)
{
    var butt = GetButt(buttId);
    if (butt == null || !butt.IsGassy)
        return null;

    return _context.Farts.Where(f => f.Butt.Id == buttId).ToList();
}
Weeks pass and GetFarts is used across the codebase. Naturally, users want to know who dealt it, so in the UI somewhere mid-level developer Susie writes:

C# code:
    var farts = GetFarts(buttId);
    var user = farts.First().User;
    NameAndShame(user);
Through some analytics and user feedback, the manager realizes that users don't care about butts or gassiness, they just care about who farted. Little junior developer Johnny is tasked with deleting that page. While doing so, he realizes that GetButt can be optimized since the user isn't being displayed anymore.

C# code:
public Butt GetButt(int id)
{
    //return _context.Butts.Include(b => b.Users).FirstOrDefault(b => b.Id == id);
    return _context.Butts.FirstOrDefault(b => b.Id == id);
}
A few days pass until you get a bug report from a user. One of your pages isn't loading correctly and now users can't name and shame gassy people. The developer tasked with fixing it looks at the code and wonders how it ever worked in the first place, fixes it, then goes around talking about Susie behind her back.

What happened was that when Susie called GetFarts() and got the user to name and shame them, the user was already loaded in the context due to the call in GetButts(). Entity Framework automatically saw that the Farts UserId match the loaded User, so it automatically wired them up. It tries to connect the object graph to what's already loaded.
When Johnny removed the User from GetButt(), it affected one tiny far away section of code in non-obvious ways. It's hard to catch because it's hard to know what's already been loaded into the context or what callers are expecting to be loaded into the context.

You could say the root of the problem was bad developers not being careful, and to some extent that's true, but this was just a simple example. Add a few developers to a non-trivial project and tons of code can be accidentally written that is dependent on previous queries. Now it's a mine-field if you try to optimize queries by removing unnecessary includes, because you can't just test where that query is used, you have to test every thing that happens after that query is used in each request.

Another thing that makes this particularly hard to protect against is that Includes are one of the hardest things to unit test. EF's in-memory database in the next version may make this easier, but as of now there's no great way to test object caching and includes without touching the database.

I've harped on the Include aspect of object caching, but there's another slightly less disruptive issue. If you query the database and load a value into EF, something changes in the database, then you re-query the database with the same context, EF will NOT overwrite your previous values with the new changed values from the database. It will look at the Id, see that the object is already loaded, then ignore all the new values. This is not as big of an issue with web requests where the context lifetime should be short, but it is definitely a problem if you have anything with a long-running context.

In all, it's easier to just instantiate the context where you need it. You gain greater control over the semantics of how and when a context should be opened, and you don't run into nasty object caching issues.

Wait, so EF uses query caching? This is optional in NHib (and should be off for most cases). It should use entity caching per id, so queries skip it. Includes would hit it if only id's are used for the joins, but the above example should lazy load the users if they aren't in the query so nothing should break, And the second example shouldn't work because the transaction should be isolated away from change in the first place. Does EF support clearing the cache before a query in that case? I'm just trying to wrap my NHib knowledge around EF because the above sounds bad.

crashdome
Jun 28, 2011
Everything Bognar said I learned about the hard way learning EF.

I handle my contexts in my service and use a CleanUp() method like so:
code:
    public abstract class DataContextServiceBase : IDataContextService
    {
        private DataContext _context;
        protected DataContext Context
        {
            get
            {
                if (_context == null)
                {
                    _context = new DataContext();
                    InitContext();
                }
                return _context;
            }
            set { _context = value; }
        }

        protected abstract void InitContext();

        public virtual void Cleanup()
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
In my concrete services you'll see something like this:
code:
        public ObservableCollection<Foo> Foos
        {
            get { if (Context == null) InitContext(); return Context.Foos.Local; }
        }
So far it's solved a lot of issue in trying to use EF objects in MVVM as actual Models.

When a view is destroyed, the ViewModel will call the services CleanUp(). I can then hang on to the ViewModel for a longer period if needed but, any reference to the original context's objects leaves when the View is garbage collected. The trouble I run into is using it in something like a TabControl or where there is navigation. My Tab Views hang on to references of the cleaned up context and it takes a complete refresh to tell it to grab the services "new" objects. I remedy this as best as possible by using Messaging with Navigation to do a complete PropertyChanged event which then Inits the new context in the service, grabs the "new" references, and releases the old references.

Still trying to figure out a better way to do that...

e: posted before finishing

crashdome fucked around with this message at 18:28 on Apr 28, 2015

-Dethstryk-
Oct 20, 2000

AuxPriest posted:

Anyone have any experience with transforming lat/long to WGS84 in a .Net language?

I've stumbled through the Esri ArcGIS SDK in .Net, but I'm not sure how much that can help you. It's a loving mess.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Funking Giblet posted:

Includes would hit it if only id's are used for the joins, but the above example should lazy load the users if they aren't in the query so nothing should break

This is true, and I didn't consider it in my post since I haven't used EF with lazy loading in years. I've seen it cause way too many performance problems to even consider using it again. It turns idiomatic C# code that looks like it's just in-memory into code that touches the database, which inevitably leads to round trip DB calls in a foreach. Nasty.

Funking Giblet posted:

And the second example shouldn't work because the transaction should be isolated away from change in the first place. Does EF support clearing the cache before a query in that case? I'm just trying to wrap my NHib knowledge around EF because the above sounds bad.

I don't think EF has any support for query caching, all the caching is done by entity Id. The specific example I was talking about is where you'd *want* to get the newer values. There's no implicit transaction in EF until you call SaveChanges(), so the queries are returning new values but the context is ignoring them. You'd have to instantiate a new context to get the new values. To my knowledge, there's not a way to clear the entire cache for each context. You *are* able to specify that a specific query should return results without checking the cache, but it also bypasses the entity cache entirely so those objects aren't change tracked.

Funking Giblet
Jun 28, 2004

Jiglightful!
This brings me back to my original point, don't encapsulate queries at all, and use projections only, even using those projections directly if possible.

(Can't believe I'm about to do this..)
code:

//WebAPI with NHib
public FartController(ISession session)
{
    _session = session;
}
pubic IEnumerable<FartyButtsDto> GetFartyButts(int id)
{
   Butt buttAlias;
   _session.QueryOver<Users>()
          .Where(x => x.UserId == id)
          .JoinQueryOver(x => x.Butts, () => buttAlias)
          .Where(x => buttAlias.HasFarted)
          .SelectList(list => list.Select(x => x.UserId)
                                  .Select(x => buttAlias.ButtId)).TransformTo<FartyButtsDto>().Future<FartButts>();
 
}
Complex, but gets the job done, I can improve this by moving it to a query object either, to make it testable outside of the controller.

Nhibernate can actually batch multiple queries in one round trip like this if you use the Future modifer, which acts like a promise for all other queries marked with future within the same transaction, which is why reusing the transaction and session actually helps.

Funking Giblet fucked around with this message at 19:09 on Apr 28, 2015

ljw1004
Jan 18, 2005

rum

chippy posted:

Does anyone know why Visual Studio would do this?

I'm referring to the first incidence of panelProducts being highlighted like that.

Yes, that's been an irritating bug in VB syntax highlighting for a while.

There are some patterns of "chains of dots" that cause it. I never figured out why.


We fixed it in VS2015. However, sorry to say we don't have plans to port the fix to older versions of VS.

Mellow_
Sep 13, 2010

:frog:

-Dethstryk- posted:

I've stumbled through the Esri ArcGIS SDK in .Net, but I'm not sure how much that can help you. It's a loving mess.

I just wrote my own functions to do the transformations after doing a bunch of math.

Surprised these things don't already exist in an easy to use format :\.

Opulent Ceremony
Feb 22, 2012

Bognar posted:

This is true, and I didn't consider it in my post since I haven't used EF with lazy loading in years. I've seen it cause way too many performance problems to even consider using it again. It turns idiomatic C# code that looks like it's just in-memory into code that touches the database, which inevitably leads to round trip DB calls in a foreach. Nasty.


As long as you're using some profiling tool in conjunction it's no problem. MiniProfiler for MVC.NET will even alert in red at the highest level to indicate a duplicated query, which usually means an N+1 EF lazy-loading issue.

RICHUNCLEPENNYBAGS
Dec 21, 2010

Bognar posted:

I don't think EF has any support for query caching, all the caching is done by entity Id.

It's only cached if you use Find; you can avoid the cache, if you want, by using Single or First or SingleOrDefault or FirstOrDefault. Then none of the problems you're talking about even come up. If you do use Find I'm pretty sure no query is run if the thing is already cached. (Or maybe not? I don't know; that was my understanding and nothing's made me question it so far but I guess it could be wrong)


Funking Giblet posted:

This brings me back to my original point, don't encapsulate queries at all, and use projections only, even using those projections directly if possible.

(Can't believe I'm about to do this..)
code:

//WebAPI with NHib
public FartController(ISession session)
{
    _session = session;
}
pubic IEnumerable<FartyButtsDto> GetFartyButts(int id)
{
   Butt buttAlias;
   _session.QueryOver<Users>()
          .Where(x => x.UserId == id)
          .JoinQueryOver(x => x.Butts, () => buttAlias)
          .Where(x => buttAlias.HasFarted)
          .SelectList(list => list.Select(x => x.UserId)
                                  .Select(x => buttAlias.ButtId)).TransformTo<FartyButtsDto>().Future<FartButts>();
 
}
Complex, but gets the job done, I can improve this by moving it to a query object either, to make it testable outside of the controller.

Nhibernate can actually batch multiple queries in one round trip like this if you use the Future modifer, which acts like a promise for all other queries marked with future within the same transaction, which is why reusing the transaction and session actually helps.
That looks kind of nice. Maybe I should look at NHibernate for my next project.

Anyway, projections are great, but in EF at least they're not really helpful if you want to mutate stuff. If you just want to do read-only queries, absolutely.

Since we're all yammering on about Entity, what's the best way to do mapping of this sort:

View model contains a collection of some other view model. These each correspond to some database entity. Based on what's in the collection, you need to modify existing entries, add new ones, and drop existing ones that aren't in the view model collection. I've done this a few ways but none of them has really satisfied me as being not noisy/technically slow if you had large inputs.

I guess maybe it would be best to sort both by ID and then go incrementing each collection? That'd avoid multiple loops at least.

RICHUNCLEPENNYBAGS fucked around with this message at 04:15 on Apr 29, 2015

Drastic Actions
Apr 7, 2009

FUCK YOU!
GET PUMPED!
Nap Ghost
If any of you are going to Build, be sure to check out the Xamarin talk on Friday. I did most of the web infrastructure for our demo (If we manage to finish it. It should be done tomorrow, but building it at all was a split second decision and we started the project three weeks ago :v:), so you may be able to see it explode in real time! Or if it works live, see some pretty cool Azure and Xamarin app interaction. At least that's the hope. We'll see!

Except for me, I couldn't go :cry:.

Drastic Actions fucked around with this message at 04:39 on Apr 29, 2015

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

RICHUNCLEPENNYBAGS posted:

It's only cached if you use Find; you can avoid the cache, if you want, by using Single or First or SingleOrDefault or FirstOrDefault. Then none of the problems you're talking about even come up. If you do use Find I'm pretty sure no query is run if the thing is already cached. (Or maybe not? I don't know; that was my understanding and nothing's made me question it so far but I guess it could be wrong)

Find searches the cache for an entity, then queries the database if it's not in the cache. No surprises happen in this use case.

FirstOrDefault will execute the query no matter what, check the Id of the result returned in the query, check the cache for the Id, then return the cached object if found. If not found in the cache it will deserialize the results then cache the entity. It will also magically hook up any navigation properties if they, too, are loaded in the cache.

aBagorn
Aug 26, 2004

Drastic Actions posted:

Or if it works live, see some pretty cool Azure and Xamarin app interaction.

Go on... :allears:

epswing
Nov 4, 2003

Soiled Meat
I sometimes write a quick program to help a client get a specific piece of work done. I don't want to mess with installers, I really just want to hand over the program and tell them to run it. Let's say a Console (or WPF, or WinForms) project has a few dependencies, which end up as dll files in the Release folder. I have to hand-pick the executable, the config file, and the dll files, move them to a new folder, zip the folder, and transfer it to the client. Then I have to help them unzip it, and tell them which file to run, or help them create a shortcut to the executable. This has many error prone steps, considering the target audience has trouble with the difference between single- and double-clicking the mouse.

I've used ILMerge to bundle the whole application into one executable, but I can never get all the arguments right the first time, and it's generally a painful process.

What would be great is a one-click "bundle all dependencies into an executable" button in Visual Studio. Does VS have such an extension I'm not aware of? Or are future VS versions considering adding this feature?

ljw1004
Jan 18, 2005

rum

Malcolm XML posted:

Unfortunately no one actually cares about windows phone or tablet so idk why they kept pushing universal apps so hard

What's exciting to me is that universal apps will run as resizable windowed apps on Desktop (yay! huge audience, and at last something I'm happy to switch to after Winforms), as well as on tablet and phone and IOT and HoloLens.

Also, with them, you can offer your windowed apps for download via the Store. Nicer than having to download apps from download.com. (edit: I guess that store stuff is being opened up to regular desktop apps as well).

ljw1004 fucked around with this message at 18:27 on Apr 29, 2015

RICHUNCLEPENNYBAGS
Dec 21, 2010

epalm posted:

I sometimes write a quick program to help a client get a specific piece of work done. I don't want to mess with installers, I really just want to hand over the program and tell them to run it. Let's say a Console (or WPF, or WinForms) project has a few dependencies, which end up as dll files in the Release folder. I have to hand-pick the executable, the config file, and the dll files, move them to a new folder, zip the folder, and transfer it to the client. Then I have to help them unzip it, and tell them which file to run, or help them create a shortcut to the executable. This has many error prone steps, considering the target audience has trouble with the difference between single- and double-clicking the mouse.

I've used ILMerge to bundle the whole application into one executable, but I can never get all the arguments right the first time, and it's generally a painful process.

What would be great is a one-click "bundle all dependencies into an executable" button in Visual Studio. Does VS have such an extension I'm not aware of? Or are future VS versions considering adding this feature?

You can output click once projects to disk.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy
Exciting stuff going on at Build:

Microsoft Launches Visual Studio Code, A Free Cross-Platform Code Editor For OS X, Linux And Windows
Microsoft Launches Its .NET Distribution For Linux And Mac

epswing
Nov 4, 2003

Soiled Meat

RICHUNCLEPENNYBAGS posted:

You can output click once projects to disk.

I get a publish folder with files in it. I want to generate exactly 1 file, transfer it, double click it.

Inverness
Feb 4, 2009

Fully configurable personal assistant.
I forgot Build was going on. Maybe we'll get a VS 2015 release date?

Since reading the C# 6 features list, I've had several "man I wish I was using C# 6" moments lately.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



epalm posted:

I get a publish folder with files in it. I want to generate exactly 1 file, transfer it, double click it.

Set up ILMerge as a build step? http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx

Embed all your assemblies? http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx

Dreadrush
Dec 29, 2008
My thoughts on the use of EF as discussed below: (for the vast majority of projects)
- let DI create a new DbContext per request - you have simplified your code a little
- just write queries directly in your controllers rather than creating a new layer that all queries must be written in - you have simplified your codebase a lot
- put common queries into helper classes returning IQueryables
- when sharing code for something more complicated, return a custom object rather than an EF object
- don't use Include

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

epalm posted:

I've used ILMerge to bundle the whole application into one executable, but I can never get all the arguments right the first time, and it's generally a painful process.

I use the Fody plugin Costura to do the same sort of thing. You'd still need to distribute the config file if you have config specific settings. https://github.com/Fody/Costura

RICHUNCLEPENNYBAGS
Dec 21, 2010

Dreadrush posted:

My thoughts on the use of EF as discussed below: (for the vast majority of projects)
- just write queries directly in your controllers rather than creating a new layer that all queries must be written in - you have simplified your codebase a lot
- don't use Include

lol. Thank you for the absolutely insane advice.

Dreadrush
Dec 29, 2008

RICHUNCLEPENNYBAGS posted:

lol. Thank you for the absolutely insane advice.

Care to elaborate?
In my experience following this advice results in simple and flexible code.

aBagorn
Aug 26, 2004

VSCode is pretty sweet. I've been playing around with it on a Ubuntu machine at work.

RICHUNCLEPENNYBAGS
Dec 21, 2010

Dreadrush posted:

Care to elaborate?
In my experience following this advice results in simple and flexible code.

I can't see any good reason to have a ton of data access and mapping code in your controller instead of in a separate class (I usually have one mapper to one controller but whatever). In fact I've done it that way and learned the hard way that it eventually grows unmanageable and changed it.

Avoiding includes is not a good idea because then you're relying on lazy loads. Why? Yes, the code is simpler, but in exchange you have code that is slow as hell.

some kinda jackal
Feb 25, 2003

 
 
I'm kind of in a daze about where Microsoft is going with .NET Core. I used to be big into C# back in the early 2000s, having done a lot of ASP.NET. These days two things have happened: I find myself wanting to re-learn C#, and all of the development I do is small console utilities that I want portable across Win/Lin/Mac, with Mac and Linux being the big hitters. It sounds like .NET Core should be right up my alley, but somehow I find myself incredibly lost when it comes to moving C# dev off of Windows with VS2013.

It's mostly my fault, but I think there's also a bit of information overload here. Admittedly I am jumping back on the ship just as Microsoft is radically shifting the paradigm, but I guess it leaves me wondering what the next step for picking up C# again should be.

I'm probably going to just install the Mono package for Mac and MonoDevelop and just stop worrying about it and start learning rather than trying to figure out every new thing or second guessing whether I should be doing this or that. Analysis paralysis.

ljw1004
Jan 18, 2005

rum

Martytoof posted:

I find myself wanting to re-learn C#, and all of the development I do is small console utilities that I want portable across Win/Lin/Mac, with Mac and Linux being the big hitters. It sounds like .NET Core should be right up my alley, but somehow I find myself incredibly lost when it comes to moving C# dev off of Windows with VS2013.

It's mostly my fault, but I think there's also a bit of information overload here. Admittedly I am jumping back on the ship just as Microsoft is radically shifting the paradigm, but I guess it leaves me wondering what the next step for picking up C# again should be.

I'm probably going to just install the Mono package for Mac and MonoDevelop and just stop worrying about it and start learning rather than trying to figure out every new thing or second guessing whether I should be doing this or that. Analysis paralysis.

Another option: watch this talk tomorrow at 2pm Pacific time:

quote:

Taking .NET Cross-Platform: Building .NET Applications on Linux and Mac
See .NET running on Linux and OSX! Join Habib Heydarian and learn the latest updates about .NET Core, the cross-platform, modular and self-contained implementation of .NET
http://channel9.msdn.com/Events/Build/2015/3-670

Factor Mystic
Mar 20, 2006

Baby's First Post-Apocalyptic Fiction

amotea posted:

I wish they'd just fix and improve WPF, and not reinvent the wheel over and over again. There is no viable alternative for desktop applications right now.

WPF is powerful enough for any UI stuff you can think of, it just needs some overhauling in some places.

Also, an updated cross-browser Silverlight would beat the hell out of the dumb Javascript hell everyone's using right now.

I also wish WPF would become less bad, so we agree on that point. However, you can take your xaml & data binding & mvvm principles and use them to build universal apps which are now much more integrated with the desktop.

And man you are behind the times wrt Silverlight. Browser plugins are dead, completely. Much better js runtimes & mobile killed it. It was a neat idea in its time but c'mon.

some kinda jackal
Feb 25, 2003

 
 

ljw1004 posted:

Another option: watch this talk tomorrow at 2pm Pacific time:

Or I could do that, thanks :)

Dreadrush
Dec 29, 2008

RICHUNCLEPENNYBAGS posted:

I can't see any good reason to have a ton of data access and mapping code in your controller instead of in a separate class (I usually have one mapper to one controller but whatever). In fact I've done it that way and learned the hard way that it eventually grows unmanageable and changed it.

Avoiding includes is not a good idea because then you're relying on lazy loads. Why? Yes, the code is simpler, but in exchange you have code that is slow as hell.

Things become unmanageable when classes take on too much responsibility and become too large. This can also happen by moving this code down a layer into another class. If each controller represents a different http resource, then your controllers will not get too large.
At this point, it is most manageable to include data access code directly in the controller. If I write this code in a separate class in another layer, then I have unnecessarily added more work and more complexity to my project.

I am not relying on lazy loading by avoiding Includes. I suggest ending queries with a Select to retrieve only the fields needed for your query.

RICHUNCLEPENNYBAGS
Dec 21, 2010

Dreadrush posted:

Things become unmanageable when classes take on too much responsibility and become too large. This can also happen by moving this code down a layer into another class. If each controller represents a different http resource, then your controllers will not get too large.
At this point, it is most manageable to include data access code directly in the controller. If I write this code in a separate class in another layer, then I have unnecessarily added more work and more complexity to my project.

I am not relying on lazy loading by avoiding Includes. I suggest ending queries with a Select to retrieve only the fields needed for your query.

OK, that's what we were all talking about a few posts ago when we mentioned "projection," but that doesn't help if you want to mutate data. For read-only queries projection is the way to go (even if you aren't going after navigation properties you will select the entire row without it).

As for your point about controllers: no, I entirely disagree. The purpose of the controller is not to do data access. I have no idea what it means for "each controller to represent a different HTTP resource."

RICHUNCLEPENNYBAGS fucked around with this message at 04:09 on Apr 30, 2015

Gul Banana
Nov 28, 2003

Factor Mystic posted:

I also wish WPF would become less bad, so we agree on that point. However, you can take your xaml & data binding & mvvm principles and use them to build universal apps which are now much more integrated with the desktop.

Weeeell.. the Windows 10 desktop. Windowed WinRT isn't being backported to even 8, is it? That means a lot of us are stuck with WPF for many years to come.

Originally, when .NET came out and took over the LOB world, it was at least in part because it supported platforms that were currently in use, not just ones that would likely eventually get some.

Gul Banana
Nov 28, 2003

Visual Studio Code is a really interesting idea which got less interesting when it was revealed that a) it's an Atom-like html app which can't open large files, and b) it doesn't have as much intellisense support as even OmniSharp provides.

Adbot
ADBOT LOVES YOU

Funking Giblet
Jun 28, 2004

Jiglightful!
https://github.com/jbogard/MediatR

This is what I use to simplify controllers. The added benefit is you could mix NHib and EF and NoSql behind the scenes, you only expose IMediator to the controllers. This also helps in horrible cases such as

code:
public SomeController(IService1 service1,IService2 service2, IService3 service3, ISession session)
{
    _service1 = service1;
    _service2 = service2;
    _service3 = service3;
   _session = session;
}

public object DoService1Thing(int id)
{
    var thingy = _session.Get<Thing>(id);
    return _service1.DoThing(thingy);
}

public object DoService2Thing()
{
    return _service2.DoThing();
}

public object DoService3Thing()
{
    return _service3.DoThing();
}

You could argue the controller should be split into three controllers, but in practice this is not what happens. If DoService1Thing() is your most used methods, you new up the other services each time it's called. This is a light example, it gets much worse in practice from what I've seen.

This could be changed to the following.

code:
public SomeController(IMediator mediator)
{
    _mediator = mediator;    
}

public object DoService1Thing(int id)
{
    return _mediator.Request(new Service1Command(id));
}

public object DoService2Thing()
{
    return _mediator.Request(new Service2Request());
}

public object DoService3Thing()
{
    return _mediator.Request(new Service3Command());
}

The mediator itself is light, the hard work is done on the Request method. You can wire up handlers with IOC too, for more flexibility.
Now each of thesse requests/commands has an associated handler, they themselves are simple pocos.
The handler looks like this.

code:
public Service1CommandHandler : IRequestHandler<Service1Command,ResponseObject>
{
    public Service1CommandHandler (IService1 service1, ISession session) {...}
    public ResponseObject Handle(Service1Command command)
    {
        var thingy = _session.Get<Thing>(command.id);
        return _service1.DoThing(thingy);
    }
}

You can do cool things like see cref="" in your command classes in order to help finding the associated handlers easier, but the biggest benefit is reusing this command/request in multiple controllers, and fulfilling each request however you want, including using any datalayer you want, per command. This goes a long way towards CQRS too if you are inclined.

This is obviously getting complex, but this is the next step whenever a controller becomes complicated. You quickly see that controllers become nothing more than wrappers around these commands, which with some clever ActionInvoker implementation, might not even need to exist at all...

I would even call my queries directly inside the command handlers, no repos or services.

Funking Giblet fucked around with this message at 08:58 on Apr 30, 2015

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