C# hate



  • @dkf said:

    non-trivial exception constructors are probably :doing_it_wrong:.

    If you're lucky, they might even land you on this site!



  • I loved C# when I used it for my internship assignment. However one thing struck me as very annoying. The software I was working on used a local SQLite database. I was happily churning out a fair amount of LINQ queries on the database, when suddenly one of them threw an exception at runtime.

    To signal that some SQL operation that my query eventually translated into, was not implemented in SQLite.

    Law of Leaky Abstractions strikes again.

    I don't know how LINQ-to-SQL is implemented, but IMO this should be a compile-time error. Or maybe it could automagically do what I did (with a BIG warning): load all the data into a collection and do the query there.



  • @marczellm said:

    I don't know how LINQ-to-SQL is implemented

    As a huge ball of mud. Basically it tries to rip apart lambdas into expressions and translate them into SQL, so for example when you call myQueryable.Where(x => x.flag == true) the underlying provider needs to translate the lambda into a LambdaExpression containing a Body of type BinaryExpression where Left side is a PropertyExpression pointing at a property named flag, and the right side... eh, you get the drill. Then it puts all this shit back together, except in SQL now.

    @marczellm said:

    but IMO this should be a compile-time error.

    How? The whole point of IQueryable is to hand out a common interface for database (or in-memory collection) querying. Your compiler doesn't really know it's handed a SQLiteQueryProvider or whatever.

    @marczellm said:

    Or maybe it could automagically do what I did (with a BIG warning): load all the data into a collection and do the query there.

    Technically it could, but that's just horrible. Let's say you write LINQ like this:

    var myCollection = products
    .GroupJoin(customers, ...)
    .GroupJoin(sales, ...)
    .Where(x => x.product.id.KindaEquals(42));
    

    Now your IQueryable provider doesn't know how to evaluate KindaEquals(), so it pulls the set and executes Where on that... except oops, you just started grabbing 50 gigs of data from a server in Hyderabad.


  • Discourse touched me in a no-no place

    @Maciejasjmj said:

    Technically it could, but that's just horrible.

    Theoretically, you'd be better off sending the code to run inside the potentially-remote database (and in fact SQLite itself supports callbacks into the host language which would be ideal for this sort of thing, though I've no idea if the SQLiteQueryProvider knows bupkis about this) but when it comes to doing this with a remote DB, the whole idea of magically shipping some chunk of code of mine off to god knows where with who knows what security implications, the whole lot just gives me the screaming heebie-jeebies. It might be safe… but it feels like it is running just so much closer to brown alert time than it needs to.

    Abstractions leak. Good abstractions merely necessarily leak less.



  • @Maciejasjmj said:

    How? The whole point of IQueryable is to hand out a common interface for database (or in-memory collection) querying. Your compiler doesn't really know it's handed a SQLiteQueryProvider or whatever.

    I guessed it's not possible, that's why I wrote "I don't know how it's implemented". But then there was this other error when the WHERE clause was a lambda expression that it couldn't translate into SQL, and that one was a compile-time warning. If my memory does not play games on me, that is. And I also have some vague recollections about getting another compile-time error along the lines of "This extension method is not supported with Linq-to-SQL". Again maybe I'm wrong here, it was more than a year ago.



  • Iiiinteresting.

    This kind of thing is probably why most Java JPA implementations let you specify a SQL dialect.

    Which makes me wonder if NHibernate or Entity Framework on the C# side do that.



  • @marczellm said:

    I don't know how LINQ-to-SQL is implemented, but IMO this should be a compile-time error.

    As far as I can tell, there is no LINQ-to-SQLite provider. Some providers claim to sorta work and there are some abandoned attempts to create an actual LINQ provider, but nothing good.

    I do see references on stack overflow about the error you may have encountered: using FirstOrDefault() compiles to SELECT TOP 1 with many LINQ providers, but SQLite doesn't support TOP. A proper SQLite provider wouldn't assume TOP is supported. That's not LINQ's fault.


  • Discourse touched me in a no-no place

    @Jaime said:

    SQLite doesn't support TOP.

    It uses LIMIT instead, though that might come in a different place in the grammar.



  • I used Entity Framework and something called `System.Data.SQLite'.



  • @marczellm said:

    I used Entity Framework and something called `System.Data.SQLite'.

    The change log for that library has LINQ fixes as recently as August of this year. Bad libraries are not LINQ's fault.



  • It does, e.g. SELECT * FROM mytable LIMIT 1

    Though LIMIT is more powerful than TOP since you can ask for records that aren't the top x, for pagination reasons. Like you can ask for 10 records starting at the 10th record to get page 2 of results.



  • I use https://github.com/Fody/PropertyChanged

    [ImplementPropertyChanged]
    public class Person 
    {        
        public string GivenNames { get; set; }
        public string FamilyName { get; set; }
    
        public string FullName
        {
            get
            {
                return string.Format("{0} {1}", GivenNames, FamilyName);
            }
        }
    }
    

    Will be compiled to:

    public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        string givenNames;
        public string GivenNames
        {
            get { return givenNames; }
            set
            {
                if (value != givenNames)
                {
                    givenNames = value;
                    OnPropertyChanged("GivenNames");
                    OnPropertyChanged("FullName");
                }
            }
        }
    
        string familyName;
        public string FamilyName
        {
            get { return familyName; }
            set 
            {
                if (value != familyName)
                {
                    familyName = value;
                    OnPropertyChanged("FamilyName");
                    OnPropertyChanged("FullName");
                }
            }
        }
    
        public string FullName
        {
            get
            {
                return string.Format("{0} {1}", GivenNames, FamilyName);
            }
        }
    
        public virtual void OnPropertyChanged(string propertyName)
        {
            var propertyChanged = PropertyChanged;
            if (propertyChanged != null)
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    No more reinventing the wheel 😄


  • Discourse touched me in a no-no place

    @Arantor said:

    Though LIMIT is more powerful than TOP since you can ask for records that aren't the top x, for pagination reasons. Like you can ask for 10 records starting at the 10th record to get page 2 of results.

    I've never experimented with the pagination stuff. I try to keep my queries specific enough that I'm not dragging enough data back from the DB for pagination to be meaningful. Yes, it's definitely specific to the nature of my applications. ;)



  • I prefer Kind of Magic. Same features, same functionality, fancier decorations.



  • @dkf said:

    I've never experimented with the pagination stuff. I try to keep my queries specific enough that I'm not dragging enough data back from the DB for pagination to be meaningful.

    Also, pagination done with LIMIT isn't stateless - it behaves unexpectedly if the underlying data set changes between pages or if the data set isn't unambiguously ordered.



  • Yeah, it's not necessarily a good idea, but it has its uses.


  • Discourse touched me in a no-no place

    @Jaime said:

    Also, pagination done with LIMIT isn't stateless - it behaves unexpectedly if the underlying data set changes between pages or if the data set isn't unambiguously ordered.

    If you're running into that sort of thing, you're :doing_it_wrong:. Pagination requires a defined repeatable order to not be :wtf: territory. Some of our apps at work have exactly this problem and it always bewilders even technical users. Knowing what's gone wrong just shifts the bewilderment to “why would they do that so wrong?!”

    :facepalm:



  • This post is deleted!


  • This post is deleted!

Log in to reply