如何解决如何从MVC Controller构建和返回多个对象
场景::我目前有一个数据仓库层,该数据仓库层是根据从.CSV读取的年度数据(该数据传递给Controller,然后将Controller传递给View层)构建一个IList(请参见下面的代码)
.CSV文件非常大。每行包含200列以上的数据:
- 年度数据(例如,十年以上,每年数学,体育和英语考试的结果以##。#%的格式)。会随着时间增长
- 非年度数据(例如姓名,性别,出生年份,邮政编码) 并非每个人每年或每个学科都有结果。
我可以读取CSV两次以构建一个单独的列表,但是更喜欢只读取一次以提高性能。
我在控制层中都需要,所以我可以使用年度和非年度数据进行一些计算(例如,每个邮政编码的平均数学得分高于平均数)。一旦我俩都加入Controller,我相信我可以取得长足的进步。
如何从相同的.CSV文件中获取其他数据,并在单独的List变量中将其返回给同一控制器,例如一个IList(annualData)和一个其余列表(otherData)。
也许有2种独立方法更好的方法,但我可能不知道提出正确的问题。
我敢肯定有一种方法可以同时返回层之间的IList和List,但是经过几次尝试,我回滚了我所有的代码,因为它们开始使我对下面的代码难以理解。
这种方法可能是正确的,但是我的执行存在缺陷,并给了我不太了解的VS建议/错误。
不要被下面的代码所迷惑,到目前为止,我已经获得了很多帮助。我对OO,C#和MVC非常陌生。在远离编码(OO天之前)的漫长休息后,我的头脑大为提高,所以请明确建议的解决方案中使用的层。
谢谢。
当前代码:
数据回购层
public class myDataRepoLayer
{
public IList<AnnualDataModel> GetAnnualDetail(string theirIDcode)
{
IList<AnnualDataModel> annualData = new List<AnnualDataModel>();
// get CSV row data by ID code
myDataModel thatData = new myDataModel();
// Read the CSV file (for the row with the unique code provided by the parameter)
using (var reader = new StreamReader("C:/myFiles/Data of the people.csv"))
using (var csv = new CsvReader(reader,CultureInfo.InvariantCulture))
{
thatData = csv.GetRecords<myDataModel>().Where(x => x.IDcode == theirIDcode).FirstOrDefault();
}
// map data to model FY2009
AnnualDataModel FY2009 = new AnnualDataModel()
{
Year = 2009,Eng = thatData.Eng2009,PE = thatData.PE2009,Maths = thatData.Maths2009
};
annualData.Add(FY2009);
// map another year's worth of data to model
AnnualDataModel FY2010 = new AnnualDataModel()
{
Year = 2010,Eng = thatData.Eng2010,PE = thatData.PE2010,Maths = thatData.Maths2010
};
annualData.Add(FY2010);
return annualData; // How do I also return a List here?
}
}
数据层
namespace mySite.Models
{
public class AnnualDataModel // This is used to build the IList of the annual data
{
public int Year { get; set; }
public Decimal? Eng { get; set; }
public Decimal? PE { get; set; }
public Decimal? Maths { get; set; }
}
}
控制器
namespace mySite.Controllers
{
public class myLessonController : Controller
{
public ActionResult HistoricPerformance()
{
myDataRepoLayer repo = new myDataRepoLayer();
// How do I get back the iList and another List with this call? How do I then use those two vars?
IList<AnnualDataModel> aData = repo.GetAnnualDetail("DDD"); //Later replace DDD with UI search field
// From the annual data get the fist and latest year data is reported,the difference (total years data) all for calcs later on,and if there were results every year
// firstYearIndex (int),lastYearIndex (int),YsofData (int),dataEveryYear (bool)
(int index0,int indexN,int ycount,bool dataAllYears) years = (0,false);
years = YearsOfData(aData);
IList<AnnualDataViewModel> vm = new List<AnnualDataViewModel>();
foreach (var y in aData)
{
AnnualDataViewModel v = new AnnualDataViewModel();
v.Year = y.Year;
v.Eng = y.Eng;
v.PE = y.PE;
v.Maths = y.Maths;
// Convert all the annual Decimal data to the format to display them in e.g. #.##%
v.TextEng = y.Eng.HasValue ? (y.Eng.Value / 100).ToString("P") : "";
v.TextPE = y.PE.HasValue ? (y.PE.Value / 100).ToString("P") : "";
v.TextMaths = y.Maths.HasValue ? (y.Maths.Value / 100).ToString("P") : ""; ;
vm.Add(v);
}
return View(vm);
}
}
}
查看模型
namespace mySite.ViewModels
{
public class AnnualDataViewModel
{
public int Year { get; set; }
public decimal? Eng { get; set; }
public decimal? PE { get; set; }
public decimal? Maths { get; set; }
public string TextEng { get; set; }
public string TextPE { get; set; }
public string TextMaths { get; set; }
}
}
HTML(查看层)
@*@model mySite.ViewModels.AnnualDataViewModel*@
@model List<mySite.ViewModels.AnnualDataViewModel>
<table style="width:100%" id="Their Annual Results">
@foreach (mySite.ViewModels.AnnualDataViewModel item in Model)
{
<tr>
<td align="right">@item.Year </td>
<td align="right">@item.TextEng </td>
<td align="right">@item.TextPE </td>
<td align="right">@item.TextMaths </td>
</tr>
}
</table>
解决方法
为了从方法返回数据结构,您可以创建一个具有两个属性的新对象,例如:
public IList<AnnualDataModel> AnnualDataModel { get; set; }
public List<OtherDataModel> OtherDataModel { get; set; }
或者从c#7开始,我们可以使用元组-包含多个字段表示的轻量级数据结构-请参见文档here
我将使用元组。考虑到这一点,结构将如下所示:
public class AnnualDataModel
{
public int Year { get; set; }
public Decimal? Eng { get; set; }
public Decimal? PE { get; set; }
public Decimal? Maths { get; set; }
public string TextEng { get; set; }
public string TextPE { get; set; }
public string TextMaths { get; set; }
}
从上面可以看到我在data
类中移动了Text属性。
public class OtherDataModel
{
public string PostCode { get; set; }
public string DOB { get; set; }
public string Gender { get; set; }
public string Name { get; set; }
}
以上是您提到的其他数据的示例。我无权访问实际的.csv文件-改正由您决定。
GetAnnualDetail()
如下所示:
public (IList<AnnualDataModel> annualData,List<OtherDataModel> otherData) GetAnnualDetail(string theirIDcode)
{
IList<AnnualDataModel> annualData = new List<AnnualDataModel>();
List<OtherDataModel> otherData = new List<OtherDataModel>();
//get data from csv and fill both List and IList
//......
//......
// Do Convert all the annual Decimal data to the format to display them in e.g. #.##% here
// Make the class responsible for getting the data responsible for its conversion
return (annualData,otherData); // How do I also return a List here?
}
现在,由于所有数据都是由负责的类检索和转换的,因此可以简化您的视图模型:
public class ViewModel
{
public IList<AnnualDataModel> AnnualDataModel { get; set; }
public List<OtherDataModel> OtherDataModel { get; set; }
}
在您的控制器中,您可以进行以下调用以获取详细信息:
MyDataRepoLayer data = new MyDataRepoLayer();
ViewModel vm = new ViewModel();
vm.AnnualDataModel = data.GetAnnualDetail("3").annualData;
vm.OtherDataModel = data.GetAnnualDetail("3").otherData;
编辑
一次调用MyDataRepoLayer
(vm.AnnualDataModel,vm.OtherDataModel) = data.GetAnnualDetail("3");
HTML模式更改为:
@model mySite.ViewModels.ViewModel
......
@foreach (AnnualDataModel annualData in Model.AnnualDataModel)
{
<tr>
....
</tr>
}
@foreach (OtherDataModel otherData in Model.OtherDataModel)
{
<tr>
....
</tr>
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。