在LINQ to Entities中只支持无参数的构造函数和初始值设定项

我在这个linqexpression式中有这个错误:

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(); 

任何想法如何解决这个问题? 我尝试用任何expression式的组合::/

没有关于“付款”的更多信息,这没有什么帮助,但是假设您想要创buildPayments对象并根据列值设置其某些属性:

 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(); 

如果您仍然想使用您的构造函数来进行初始化而不是属性(有时这种行为是为了初始化目的而需要),通过调用ToList()ToArray()枚举查询,然后使用Select(…) 。 因此,它将使用LINQ to Collections,并且无法使用Select(…)参数调用构造函数的限制将会消失。

所以你的代码应该是这样的:

 var naleznosci = db.Naleznosci .Where(nalTmp => nalTmp.idDziecko == idDziec) .ToList() // Here comes transfer to LINQ to Collections. .Select(nalImp => 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(); 

刚刚遇到这个错误,我想我会补充说,如果Paymenttypes是一个struct ,你也会遇到同样的错误,因为structtypes不支持无参数的构造函数。

在这种情况下,将Payment转换为类并使用对象初始化程序语法将解决此问题。

如果你像我一样,不想为每个你正在构build的查询填充你的属性,还有另一种方法来解决这个问题。

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

此时你有一个包含匿名对象的IQueryable。 如果你想用一个构造函数填充你的自定义对象,你可以简单地做这样的事情:

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

现在您的自定义对象(将两个对象作为参数)可以根据需要填充您的属性。

首先,我会避免与解决scheme

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

这需要一个空的构造函数,并忽略封装,所以你说新的Payments()是没有任何数据的有效付款,而是对象必须至less有一个值,可能还有其他必需的字段,取决于你的域名。

有必要的领域的构造函数,但只带来需要的数据:

 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(); 

对,像这样试试….

 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(); 

这将使用无参数的构造函数重新创buildPayment对象,然后初始化大括号内所列的属性。 { }

你可以尝试做同样的事情,但使用扩展的方法。 数据库使用的提供者是什么?

 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(); 

另外,如果你想使用一个具有多个对象的构造函数来初始化,如果Linq没有返回任何值,你可能会遇到错误。

所以你可能想要做这样的事情:

 (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(); 

抱歉迟到了,但是我发现后,我认为这应该是共享的,因为它是我能find的最干净,最快和节省内存的实现。

根据你的例子,你会写:

 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); } 

这里最大的优点就是Damien Guard在链接的评论中指出:

  • 保证您在每次出现时都使用初始化模式。
  • 用法通过var foo = createPayments(bar); 以及通过myIQueryable.ToPayments()使用的可能。

我今天遇到了同样的问题,我的解决scheme与Yoda列出的类似,不过它只能用stream利的语法。

使我的解决scheme适应您的代码:我将下面的静态方法添加到对象类

  /// <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 }; } 

然后将基本查询更新为以下内容:

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

这在逻辑上等同于James Manning的解决scheme,其优点是将大量的成员初始化推送到类/数据传输对象

注意:最初我使用了更多的描述性名称,即“初始化程序”,但在回顾了我如何使用它之后,我发现“初始化程序”已经足够了(至less对于我的目的而言)。

最后注意:
在提出这个解决scheme之后,我原本以为分享相同的代码变得很简单,并且使其适用于查询语法。 我不再相信如此。 我认为,如果你想能够使用这种types的速记结构,你将需要一个方法,每个(查询,stream利)如上所述stream利,可以存在于对象类本身。

对于查询语法,将需要一个扩展方法(或正在使用的基类之外的某种方法)。 (因为查询语法想要操作IQueryable而不是T)

这里是我用来最终得到这个查询语法工作的样本。 (尤达已经确定了这一点,但是我认为这个用法可能会更清晰,因为我一开始并没有这样做)

 /// <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 }; } 

和用法

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

除了前面提到的方法外,还可以将其parsing为Enumerable集合,如下所示:

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

当build立一个匿名对象时,这也有额外的好处,例如:

  (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(); 

但是记住,将一个集合parsing为Enumerable会将其拉到内存中,因此可能会占用大量资源! 应该谨慎使用这里。