嗨我有一个数组,它接收制造商和国家,由于某种原因,当数组回来时,数组的顺序有时会改变。
以下是Linq查询:
var array = (from xx in _er.UserRoles
join xy in _er.Countries on xx.CountryId equals xy.Id
join xz in _er.Manufacturers on xx.ManufacturerId equals xz.Id
where xx.UserId == userId
select new List<string> { xz.Description, xy.Name }).ToArray();
其中: xz.Description是制造商 xy.Name是国家/地区
在我的数组中,我希望得到以下内容:
[0] Count = 2
[0] Dove
[1] Uk
[1] Count = 2
[0] Dove
[1] France
[2] Count = 2
[0] Sure
[1] UK
...
但在某些情况下,我得到以下内容:
[0] Count = 2
[0] Dove
[1] Uk
[1] Count = 2
[0] France
[1] Dove
[2] Count = 2
[0] UK
[1] Sure
...
当我在数据库中运行查询以检查每个制造商是否有他们最初做的国家时,我认为可能是这样。
有人可以就这可能发生的原因提出建议吗?
修改
这是sql查询和一些示例数据:
select m.Description, c.Name from UserRoles ur
join Countries c on ur.CountryId = c.Id
join Manufacturers m on ur.ManufacturerId = m.Id
where ur.userid = 435
示例数据:
Description Name
Lynx United Kingdom
Persil United Kingdom
Dove Brazil
Dove Canada
Dove Germany
Dove France
Dove United Kingdom
Dove Netherlands
Dove United States
Surf United Kingdom
Comfort United Kingdom
Sure United Kingdom
Bertolli United Kingdom
Bertolli United States
修改2
以下是对我正在做的事情的更多解释,因此可以解释更多关于我需要的最终结果:
在我的控制器中,我将数组放入会话中:
控制器代码:
var userManuCountry = _userRoleRepository.GetCountryAndManufacturerForUser(u.Id);
Session["userManuCountry"] = userManuCountry;
存储库代码:
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public string[,] GetCountryAndManufacturerForUser(int userId)
{
var array = (from xx in _er.UserRoles
join xy in _er.Countries on xx.CountryId equals xy.Id
join xz in _er.Manufacturers on xx.ManufacturerId equals xz.Id
where xx.UserId == userId
select new List<string> { xz.Description, xy.Name }).ToArray();
return CreateRectangularArray(array);
}
static T[,] CreateRectangularArray<T>(IList<T>[] arrays)
{
// TODO: Validation and special-casing for arrays.Count == 0
int minorLength = arrays[0].Count();
T[,] ret = new T[arrays.Length, minorLength];
for (int i = 0; i < arrays.Length; i++)
{
var array = arrays[i];
if (array.Count != minorLength)
{
throw new ArgumentException
("All arrays must be the same length");
}
for (int j = 0; j < minorLength; j++)
{
ret[i, j] = array[j];
}
}
return ret;
}
另一个控制器 - 我正在使用该会话列出制造商的国家/地区:
/// <summary>
/// et the specific countries for user and manufacturer
/// </summary>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Get)]
// [ValidateAntiForgeryToken]
// [Authorize(Roles = "ReportingDashboardAccess")]
public ActionResult GetListOfCountriesForUserManufacturer(int userId, string manu)
{
manu = manu.Trim();
// get the specific countries for user and manufacturer
var countries = new List<string>();
//here we want to use the manu to get the countries from seesion rather than db - this is a multidimensional array
string[,] manuCountry = (string[,])Session["userManuCountry"];
var addCountry = false;
//loop through to find countries for each manufacturer
for (int row = 0; row < manuCountry.GetLength(0); row++)
{
for (int col = 0; col < manuCountry.GetLength(1); col++)
{
string result = manuCountry[row, col];
result.Trim();
if (addCountry == true && col == 1)
{
//addcountry has been set to true so add it
countries.Add(result);
addCountry = false;
}
else if (addCountry == true && col == 0)
{
addCountry = false;
}
if (result == manu)
{
//the next one that comes through is the country
addCountry = true;
}
}
}
countries.Sort();
ViewData["allCountries"] = new SelectList(countries);
return View("CountriesParam");
}
非常感谢!
答案 0 :(得分:2)
Collection Initializers(new List<string> { xz.Description, xy.Name }
)应该保留表达式中指定的项的顺序,因此您的代码应该可以工作。
我猜想有些东西可以在创建的列表上运行,并以某种方式激活排序。
也就是说,对具有单独含义的值使用列表(或任何集合)是非直观的。即使它们都是字符串,值也不具有相同的上下文。给它们明确不同的容器会好得多。例如现在,如果你用数据填充几个文本框,你可以使用:
txtName.Text = list[0];
txtCountry.Text = list[1];
并且很难看到并诊断出一个错误。如果您使用
将结果放在单独的实体(例如匿名类)中select new { Name = xz.Description, Country = xy.Name }
你可以使用
txtName.Text = myObject.Name;
txtCountry.Text = myObject.Country
关于edit2:如果我正确了解您的情况,您需要的是获取制造商允许的国家/地区列表。这类数据的一个很好的容器是Dictionary<string, IEnumerable<string>>
,而不是string[,]
。
我会像这样重构LINQ:
//gets the data from the database
var data = (from xx in _er.UserRoles
join xy in _er.Countries on xx.CountryId equals xy.Id
join xz in _er.Manufacturers on xx.ManufacturerId equals xz.Id
where xx.UserId == userId
select new { Name = xz.Description, Country = xy.Name });
//formats the data into a dictionary
var result = data.GroupBy(a => a.Name)
.ToDictionary(// the name of the product
g => g.Key,
// the list of countries for the product
g => g.Select(a => a.Country).ToList());
return result;
然后使用它(在GetListOfCountriesForUserManufacturer
中),如下所示:
public ActionResult GetListOfCountriesForUserManufacturer(int userId, string manu)
{
manu = manu.Trim();
//I'm not too crazy about sesiion usage, but that's a whole other issue
var manuCountry = (Dictionary<string, List<string>>)Session["userManuCountry"];
// get the specific countries for user and manufacturer
var countries = manuCountry[manu];
countries.Sort();
ViewData["allCountries"] = new SelectList(countries);
return View("CountriesParam");
}
答案 1 :(得分:0)
在您的select语句中,您创建的列表实际上是无序的。 我建议你创建一个带有描述,名称(可能还有更多属性)的新类,因为在我看来,列表中的每个项目都有一个特定的来源,而不是列表。
如果你不想创建一个新类,你总是可以把它放在这样的元组中:
var array = (from xx in _er.UserRoles
join xy in _er.Countries on xx.CountryId equals xy.Id
join xz in _er.Manufacturers on xx.ManufacturerId equals xz.Id
where xx.UserId == userId
select new Tuple<string,string> (xz.Description, xy.Name)).ToArray();