147

I have this error in this linq expression :

var naleznosci = (from nalTmp in db.Naleznosci
                              where nalTmp.idDziecko == idDziec
                              select new Payments
                              (
                                  nalTmp.Dziecko.Imie,
                                  nalTmp.Dziecko.Nazwisko,
                                  nalTmp.Miesiace.Nazwa,
                                  nalTmp.Kwota,
                                  nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                                  nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                  nalTmp.DataRozliczenia,
                                  nalTmp.TerminPlatnosci
                              )).ToList();

Any idea how solve this problem? I try with any combination of expression... :/

netmajor
  • 6,507
  • 14
  • 68
  • 100
  • 1
    can you show the Payments class? or at least the ctor getting called here, and specifically whether that 8-param ctor call can be safely swapped out for a 0-param ctor call and setting 8 properties on the object? – James Manning Aug 26 '10 at 05:01
  • 25
    I got this same error when using a Struct instead of a Class for the object I was "newing." – Joshua Stafford Sep 23 '13 at 17:19
  • 3
    TL;DR thing is that EF-LINQ is trying to send the select statement to the EF provider, ie. convert it into SQL. To get out of EF-LINQ, call ToList() before any object creation. –  Nov 07 '16 at 21:40

14 Answers14

134

without more info on 'Payments' this doesn't help much, but assuming you want to create a Payments object and set some of its properties based on column values:

var naleznosci = (from nalTmp in db.Naleznosci
                              where nalTmp.idDziecko == idDziec
                              select new Payments
                              {
                                  Imie = nalTmp.Dziecko.Imie,
                                  Nazwisko = nalTmp.Dziecko.Nazwisko,
                                  Nazwa= nalTmp.Miesiace.Nazwa,
                                  Kwota = nalTmp.Kwota,
                                  NazwaRodzajuOplaty = nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                                  NazwaTypuOplaty = nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                  DataRozliczenia = nalTmp.DataRozliczenia,
                                  TerminPlatnosci = nalTmp.TerminPlatnosci,
                              }).ToList();
James Manning
  • 13,429
  • 2
  • 40
  • 64
  • 10
    This works great, don't forget to add an empty constructor for the class. – live-love Aug 10 '11 at 20:21
  • 61
    Just to add to this answer, you cannot do this with Structs, only Classes - took me a bit to figure that out! – naspinski Dec 06 '12 at 20:30
  • 4
    Yes, I think Tony's answer is better than this one because it actually solves the immediate problem at hand, whereas this one circumvents the problem by changing the nature of the Payments class and possibly preventing it from being immutable. – Stephen Holt Apr 09 '14 at 15:51
  • 2
    this looks ugly af. Any better way with EF6? – Toolkit Nov 18 '17 at 09:32
125

If you still want to use your constructor for initialization and not properties (sometimes this behaviour is desired for initialization purposes), you will need to use LINQ to Collections at some point, because LINQ to SQL doesn't know how to translate constructors to SQL queries. You can do that by using AsEnumerable().

So your code should look something like this:

var naleznosci = 
    db.Naleznosci
        .Where(nalTmp => nalTmp.idDziecko == idDziec)
        .Select(nalTmp => new
            {
                DzieckoImie = nalTmp.Dziecko.Imie,
                DzieckoNazwisko = nalTmp.Dziecko.Nazwisko,
                MiesiaceNazwa = nalTmp.Miesiace.Nazwa
                Kwota = nalTmp.Kwota,
                NazwaRodzajuOplaty = nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                NazwaTypuOplaty = nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                DataRozliczenia = nalTmp.DataRozliczenia,
                TerminPlatnosci = nalTmp.TerminPlatnosci
            }) // Select necessary columns from DB into anonymous type.
        .AsEnumerable() // Here comes transfer to LINQ to Collections.
        .Select(nalImp => new Payments
            (
                nalTmp.DzieckoImie,
                nalTmp.DzieckoNazwisko,
                nalTmp.MiesiaceNazwa,
                nalTmp.Kwota,
                nalTmp.NazwaRodzajuOplaty,
                nalTmp.NazwaTypuOplaty,
                nalTmp.DataRozliczenia,
                nalTmp.TerminPlatnosci
            )) // Use constructor to create your models.
        .ToList();
Tony
  • 1,422
  • 1
  • 11
  • 12
  • This is great answer. In general, I like to create copy-constructor like constructors to avoid long list of property assignment and to promote code reuse. Before seeing this answer, I was forced to use the property assignment approach and I really hate it. Thanks! – newman Aug 02 '13 at 20:07
  • 25
    Just to clarify why this works, the problem with the originally stated code is that Entity Framework attempts to pass the constructor call through to the SQL along with the rest of the LINQ query, and of course there is no way for SQL to go about constructing complex objects! By inserting the ToList() call you move the enumerable from a not-yet-executed SQL query to a concrete list of objects in memory, which you can then manipulate in any way you like. – Stephen Holt Apr 09 '14 at 15:53
  • 22
    Don't use `ToX()` for this, use `AsEnumerable()`. – Rawling Aug 04 '14 at 09:47
  • 2
    .ToList() // Here comes transfer to LINQ to Collections. is the line that resolves the issue for me. – Ram May 11 '15 at 09:04
  • This code is the way to go when you need to have a POCO that you need to restrict use of a parameter less constructor. it removes the need for mapping or helper classes which just add more layers when they are not needed. +1 – Lawrence Thurman Aug 15 '15 at 13:46
  • 18
    Be aware that this will select *all* columns at the db level where as normally it will only select the required columns – Hugh Jeffner Apr 06 '16 at 18:02
  • 4
    Not only that but you're probably going to have multiple enumerations. I don't like this solution. – Bluebaron Apr 29 '16 at 03:00
  • use an anonymous type for the sql projection and then use .AsEnumerable instead of the first ToList. This would only bring the required fields from the database and will only create one list in memory (and only iterates the results once to make the final projection and create the list) – nflash Feb 02 '21 at 16:08
48

Having just encountered this error myself, I thought I would add that if the Payment type is a struct, you would also encounter the same error because struct types do not support parameterless constructors.

In that event, converting Payment to a class and using the object initializer syntax will resolve the issue.

Gene C
  • 2,010
  • 26
  • 34
  • This solves the problem form me. Actually this query with struct selector is supported in LINQ-2-SQL and it is an issue when you are upgrading to EntityFramework. – Tomas Kubes Sep 26 '15 at 15:59
  • I hate structs. They never end up doing what I want – Simon_Weaver Sep 29 '16 at 00:23
  • Created a `DateTime` (which is a struct) inside my Query, which results in the same Error. extracting it to a local Variable fixed it for me. Thanks for the struct hint. – LuckyLikey Jul 13 '17 at 09:45
26

If you're like me and don't want to have to populate your properties for each query you're building, there is another way to solve this issue.

var query = from orderDetail in context.OrderDetails
            join order in context.Orders on order.OrderId equals orderDetail.orderId
            select new { order, orderDetail };

At this point you have an IQueryable containing an anonymous object. If you want to populate your custom object with a constructor you can simply do something like this:

return query.ToList().Select(r => new OrderDetails(r.order, r.orderDetail));

Now your custom object (which takes two objects as a parameter) can populate your properties as needed.

Justin Helgerson
  • 24,900
  • 17
  • 97
  • 124
  • This worked for me and came to be the cleanest solution. Those who've suggested to eliminate the constructor and use initializer syntax must not have had logic within the constructor. That is the only time that I lean on constructors to populate properties for an object. Thank you for sharing. – Bonez024 Jun 18 '19 at 14:00
12

First I would avoid the solution with

from ....
select new Payments
{
  Imie = nalTmp.Dziecko.Imie,
  ....
}

This requires an empty constructor and ignores encapsulation so you are saying new Payments() is a valid payment without any data, but instead the object must have at least a value and probably other required fields depending on your domain.

It's better to have a constructor for required fields but only bring needed data:

from ....
select new
{
  Imie = nalTmp.Dziecko.Imie,
  Nazwisko = nalTmp.Dziecko.Nazwisko
  ....
}
.ToList() // Here comes transfer to LINQ to Collections.
.Select(nalImp => new Payments
 (
  nalTmp.Imie,//assume this is a required field
  ...........
  )
  {
     Nazwisko = nalTmp.Nazwisko //optional field
  })
.ToList();
eugen
  • 464
  • 5
  • 16
5

Sorry for being late to the party, but I after finding this, I thought this should be shared as it's the cleanest, fastest and also memory-saving implementation I could find.

Adapted to your example, you'd write:

public static IQueryable<Payments> ToPayments(this IQueryable<Naleznosci> source)
{
  Expression<Func<Naleznosci, Payments>> createPayments = naleznosci => new Payments
  {
    Imie = source.Dziecko.Imie,
    Nazwisko = source.Dziecko.Nazwisko,
    Nazwa= source.Miesiace.Nazwa,
    Kwota = source.Kwota,
    NazwaRodzajuOplaty = source.RodzajeOplat.NazwaRodzajuOplaty,
    NazwaTypuOplaty = source.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
    DataRozliczenia = source.DataRozliczenia,
    TerminPlatnosci = source.TerminPlatnosci,
  };

  return source.Select(createPayments);
}

The big advantages here (as Damien Guard pointed out in the comments at the link) are:

  • Safes you from using initialization pattern on each occurrence.
  • Usage via var foo = createPayments(bar); as well as myIQueryable.ToPayments() is possible.
Yoda
  • 539
  • 1
  • 9
  • 18
4

You can try to do the same, but using the methods of extension. What is the provider of the database use?

var naleznosci = db.Naleznosci
                          .Where<TSource>(nalTmp => nalTmp.idDziecko == idDziec)
                          .Select<TSource, TResult>(
                             delegate(TSource nalTmp) { return new Payments
                             (
                                 nalTmp.Dziecko.Imie,
                                 nalTmp.Dziecko.Nazwisko,
                                 nalTmp.Miesiace.Nazwa,
                                 nalTmp.Kwota,
                                 nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                                 nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                 nalTmp.DataRozliczenia,
                                 nalTmp.TerminPlatnosci
                             ); })
                          .ToList();
3

I had the same problem today and my solution was similar to what Yoda listed, however it only works with fluent syntax.

Adapting my solution to your code: I added the following static method to the object class

    /// <summary>
    /// use this instead of a parameritized constructor when you need support
    /// for LINQ to entities (fluent syntax only)
    /// </summary>
    /// <returns></returns>
    public static Func<Naleznosci, Payments> Initializer()
    {
        return n => new Payments
        {
             Imie = n.Dziecko.Imie,
             Nazwisko = n.Dziecko.Nazwisko,
             Nazwa = n.Miesiace.Nazwa,
             Kwota = n.Kwota,
             NazwaRodzajuOplaty = n.RodzajeOplat.NazwaRodzajuOplaty,
             NazwaTypuOplaty = n.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
             DataRozliczenia = n.DataRozliczenia,
             TerminPlatnosc = n.TerminPlatnosci
        };
    }

and then updated the base query to the following:

var naleznosci = (from nalTmp in db.Naleznosci
    where nalTmp.idDziecko == idDziec
    select new Payments.Initializer());

This is logically equivalent to James Manning's solution with the advantage of pushing the bloat of member initialization to the Class / Data Transfer Object

Note: Originally I was using more descriptive names that "Initializer" but after reviewing how I was using it, I found that "Initilizer" was sufficient (at least for my purposes).

Final Note:
After coming up with this solution I was originally thinking it would be simple to share the same code and adapt this to work for Query syntax as well. I am no longer believe that to be the case. I think that if you want to be able to use this type of shorthand construction you would need a method for each (query,fluent) fluent as described above which can exist in the object class itself.

For query syntax an extension method (or some method outside of the base class being used) would be required. (since query syntax wants to operate an IQueryable rather than T)

Here is a sample of what I used to finally get this to work for query syntax. (Yoda already nailed this but I think the usage could be clearer because I didn't get it at first)

/// <summary>
/// use this instead of a parameritized constructor when you need support
/// for LINQ to entities (query syntax only)
/// </summary>
/// <returns></returns>
public static IQueryable<Payments> Initializer(this IQueryable<Naleznosci> source)
{
    return source.Select(
        n => new Payments
        {
            Imie = n.Dziecko.Imie,
            Nazwisko = n.Dziecko.Nazwisko,
            Nazwa = n.Miesiace.Nazwa,
            Kwota = n.Kwota,
            NazwaRodzajuOplaty = n.RodzajeOplat.NazwaRodzajuOplaty,
            NazwaTypuOplaty = n.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
            DataRozliczenia = n.DataRozliczenia,
            TerminPlatnosc = n.TerminPlatnosci
    };
}

and the usage

var naleznosci = (from nalTmp in db.Naleznosci
    where nalTmp.idDziecko == idDziec
    select nalTmp).Initializer().ToList();
wode
  • 236
  • 3
  • 8
  • added a section regarding query syntax for completeness when I realized my initial answer did not extend well. @yoda's anwer is probably better in regard to query syntax. – wode Mar 31 '17 at 23:33
1

In addition to the aforementioned methods, you can also parse it as an Enumerable collection, like so:

(from x in table
....
).AsEnumerable()
.Select(x => ...)

This also has the added benefit of making life easier when building an anonymous object, like this:

 (from x in tableName
select x.obj)
.Where(x => x.id != null)
.AsEnumerable()
.Select(x => new {
   objectOne = new ObjectName(x.property1, x.property2),
   parentObj = x
})
.ToList();

Remembering, however, that parsing a collection as Enumerable pulls it into memory, so it can be resource intensive! Caution should be used here.

XtraSimplicity
  • 5,704
  • 1
  • 28
  • 28
1

yeh, try it like this....

var naleznosci = (from nalTmp in db.Naleznosci
                              where nalTmp.idDziecko == idDziec
                              select new Payments()
                              {
                                  Dziecko.Imie,
                                  Dziecko.Nazwisko,
                                  Miesiace.Nazwa,
                                  Kwota,
                                  RodzajeOplat.NazwaRodzajuOplaty,
                                  RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                  DataRozliczenia,
                                  TerminPlatnosci
                              }).ToList();

this will new up your Payment object using a parameterless constructor, and then initialize the properties that are listed inside the curly braces { }

Muad'Dib
  • 28,542
  • 5
  • 55
  • 68
  • 3
    FYI the `()` in the Payemnts is not needed, so it can be `select new Payments { // init values } – PostMan Aug 25 '10 at 23:54
  • now I have error : Cannot initialize type 'Payments' with a collection initializer because it does not implement 'System.Collections.IEnumerable' – netmajor Aug 26 '10 at 00:23
  • right - if you were creating an anon type (instead of an instance of the Payments class), Muad's code would be fine since the properties to set would be implicitly the names of the properties being read from. Since it's a 'real' class, though, you would need to specify which properties to set to the various values. – James Manning Aug 26 '10 at 05:05
1

Also, if you want to use a constructor with multiple objects to initialize, you might get error if no values are returned by Linq.

So you might want to do something like this:

(from x in table_1
   join y in table_2
   on x.id equals y.id
   select new {
   val1 = x,
   val2 = y
})
.DefaultIfEmpty()
.ToList()
.Select(a => new Val_Constructor(a.val1 != null ? a.val1 : new Val_1_Constructor(),
                            a.val2 != null ? a.val2 : new Val_2_Constructor()))
.ToList();
Mahesh
  • 3,727
  • 1
  • 39
  • 49
1

Just use ToList() before the Select statement.. something like that:

myDbSet.Where(x => something that minimizes the number of items).ToList().Select(...)

The actual DbSet is not out of the db yet. After calling ToList() you're playing with objects, and then you can use a non-default constructor in the query.

Not the most efficient way usage-time wise, but it's an option on small sets.

eiran
  • 1,378
  • 15
  • 16
  • 1
    DbSet.ToList will dump your entire table into memory, and the DbSet is not "saved as a query, it's not fulfilled yet". Calling ToList will execute the query immediately. – nflash Feb 02 '21 at 16:09
  • you're right! i don't know what i was thinking.. editing:) – eiran Feb 08 '21 at 17:35
0

Although it is late to answer, it could still help someone in distress. Since LINQ to entities do not support the parameter-less object constructions. However, the projection methods for IEnumerable.

So prior to selection, just convert your IQueryable to IEnumerable by using this code:

var result = myContext.SomeModelClass.AsEnumerable().Select(m => m.ToString());

It will work fine. However, it will, of course, loose the benefits of native queries.

0
IQueryable<SqlResult> naleznosci = (from nalTmp in db.Naleznosci
                              where nalTmp.idDziecko == idDziec
                              select new Payments
                              {
                                  Imie = nalTmp.Dziecko.Imie,
                                  Nazwisko = nalTmp.Dziecko.Nazwisko,
                                  Nazwa= nalTmp.Miesiace.Nazwa,
                                  Kwota = nalTmp.Kwota,
                                  NazwaRodzajuOplaty =                          nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                              NazwaTypuOplaty = nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                              DataRozliczenia = nalTmp.DataRozliczenia,
                              TerminPlatnosci = nalTmp.TerminPlatnosci,
                          });
Repeater1.DataSource  = naleznosci.ToList(); 
Repeater1.DataBind();


public class SqlResult
{
        public string Imie { get; set; }
        public string Nazwisko { get; set; }
        ...
}