C#Linq无效操作异常
我目前正在学习C#,并试图掌握LINQ的窍门。我正在尝试创建两个类:Store和products,我希望根据相应的ID返回其中的对象。我计划使用LINQ执行此操作,但遇到了此错误 System.InvalidOperationException:'未能比较数组中的两个元素。' ArgumentException:至少一个对象必须实现IComparable 当然,我试图通过添加如下内容将IComparable实现到类中:C#Linq无效操作异常,c#,linq,C#,Linq,我目前正在学习C#,并试图掌握LINQ的窍门。我正在尝试创建两个类:Store和products,我希望根据相应的ID返回其中的对象。我计划使用LINQ执行此操作,但遇到了此错误 System.InvalidOperationException:'未能比较数组中的两个元素。' ArgumentException:至少一个对象必须实现IComparable 当然,我试图通过添加如下内容将IComparable实现到类中: 公共类存储:i可比较 { 公共整数比较([AllowFull]存储其他)
公共类存储:i可比较
{
公共整数比较([AllowFull]存储其他)
{
抛出新的NotImplementedException();
}
}
所以您有两个表:存储
和产品
。显然,每个产品都属于一个商店,即外键Product.StoreId
所指的商店
要进行调试,您已经尝试通过删除OrderBy语句来简化LINQ,以查看问题是在联接中还是在OrderBy中,当然,您还尝试只执行OrderBy而不执行联接。如果不是:去顽皮的地方半小时
下面的方法有效吗
仅加入:
var result = Stores.Join(Products, // Join Stores and Products
store => store.Id, // from every Store take the primary key
product => product.StoreId, // from every Product take the foreign key
// parameter resultSelector: from every matching Store and Product make one new:
(store, product) => new
{
Market = store.Name,
Product = product,
})
.ToList();
我想是的,因为例外是关于IComparer
,而不是关于IEqualityComparer
第二次尝试:订购商店和产品:
var sortedStores = marketPlaces.OrderBy(store => store.ID).ToList();
var sortedProducts = products.OrderBy(product => product.Names).ToList();
哪一个不行?我认为第二个是因为Product.Names
是一个字符串[]
。
您还没有告诉LINQ它应该如何比较两个string[]
对象,或者换句话说:
我有两个string[]
对象,哪一个应该先出现
因此,为了对产品名称进行排序,我们需要一个实现IComparable
的对象。
制作一个IComparable并不难。问题可能更多地存在于需求中:如果您有两个字符串数组产品名称,哪一个成为第一个
public class ProductNamesComparer : IComparer<string[]>
{
public int Compare(string[] x, string[] y)
{
// TODO: find out if x comes before y (return -1)
// or after y (return +1)
// or don't care (return 0)
}
}
你想要的是:
Store 1 a "Supermarket" sells the following Products:
"Vegetables" with price 3.00
"Dairy" with price 2.00
"Fruits" with price 1.50
Store 2 "Electronics" sells the following Products:
"Portable Electronics" with price 200.00,
"Stationary Electronics" with price 750.00,
"Medical Electronics" with price 550.00
Store 3 ... etc.
如果需要,请首先将产品名称与其价格相结合:
StoreId = 1 has the following products with their prices:
Name = "Vegetables"; Price 3.00
Name = "Dairy"; Price 2.00
Name = "Fruits"; Price 1.50
StoreId = 2 has the following products with their prices:
Name = "Portable Electronics"; Price 200.00
...
我假设你的产品价格,第一个价格属于第一个产品名称,第二个价格是第二个产品名称的价格。我们必须以某种方式将它们匹配为组合:{Product Name;Product Price}
如果你有两个序列A和B,并且你想组合它们,这样你就有了<代码> {a(0),b(0)},{a(1),b { 1 }},{a[4],b[2 ] }< /> >等,考虑使用
的重载之一。 换句话说:从产品序列中的每个产品中,创建一个具有以下属性的新对象:- StoreId:产品的属性StoreId的值
- NamePriceCompositions:包含<代码>{名称[0]、价格[0]}、{名称[1]、价格[1]}等组合的列表
StoreId = 1, NamePriceCombinations = { { Name = "Vegetables"; Price 3.00},
{ Name = "Dairy"; Price 2.00},
{ Name = "Fruits"; Price 1.50} },
StoreId = 2; NamePriceCombinations = { { Name = "Portable Electronics"; Price 200.00},
...
我们只需要把它和商店联系起来。使用
如果您想要包含零个或多个子项的项目,如学校及其学生、客户及其订单或商店销售的产品,请使用GroupJoin
如果您想要相反的方式:“物品与它所属的(恰好一个)物品”,如学生与他就读的学校,或与销售此产品的商店的产品,请使用Join
我们想要“有他们销售的产品的商店”,所以我们使用GroupJoin
var storesWithTheProductsTheySell = MarketPlaces.GroupJoin(productsWithTheirPrices,
store => store.Id, // from every store take the primary key
products => product.StoreId, // from every product, take the foreign key
(store, productsOfThisStore) => new
{
// Select the Store properties that you plan to use:
Market = store.Name,
...
Products = productsOfThisStore.Select(product => new
{
Name = product.Name,
Price = product.Price,
})
.ToList(),
});
当然,你可以在一个大LINQ声明中做到这一点。由于中间结果是IEnumerable,这不会大大提高效率,但我认为可读性会大大降低。
orderby market2.Names
-您是否尝试按字符串[]
排序?您在代码中使用以下行抛出错误:throw new NotImplementedException();如果您注释掉“orderbymarket2.Names”一行,代码就会运行。@KlausGütter我试图按商店的ID来订购它。So:MarketPlace.Add(newstore{Name=“SuperMarket”,ID=1});添加(新产品{name=newstring[]{“蔬菜”、“乳制品”、“水果”},价格=新双[]{3.00,2.00,1.50},StoreID=1});相互通信。@jdweng我也试图更改它返回的内容,但错误仍然存在。另外,在评论这一行时,它会打印商店的名称,但不会打印其他列表中我想要的产品或其他值。非常感谢,这非常有用。事实上,我以前从未与IComparer合作过,所以这让人感到困惑,而且我对C#还是个新手,所以使用Enumerable有时对我来说很难理解。我对LINQ有一个基本的了解,我正在试图弄清楚Join是如何工作的,您对您的解决方案给出了非常好的解释。我不是很了解所有的事情,但我会研究它来了解更多并理解您的解决方案。
StoreId = 1, NamePriceCombinations = { { Name = "Vegetables"; Price 3.00},
{ Name = "Dairy"; Price 2.00},
{ Name = "Fruits"; Price 1.50} },
StoreId = 2; NamePriceCombinations = { { Name = "Portable Electronics"; Price 200.00},
...
var storesWithTheProductsTheySell = MarketPlaces.GroupJoin(productsWithTheirPrices,
store => store.Id, // from every store take the primary key
products => product.StoreId, // from every product, take the foreign key
(store, productsOfThisStore) => new
{
// Select the Store properties that you plan to use:
Market = store.Name,
...
Products = productsOfThisStore.Select(product => new
{
Name = product.Name,
Price = product.Price,
})
.ToList(),
});