2

我正在使用 MVC3、C# 并使用 Razor。我没有始终如一地使用 MVC,所以我经常不得不重新学习东西......我想要一个显示学校列表(来自指定状态)和嵌套学生列表(来自那所学校)的视图中间名“鲍勃”。

看起来很简单,但到目前为止我还没有找到解决方案。

例如:查看

马里兰州的结果

我的第一所学校: - 比利鲍勃约翰逊 - 莎莉鲍勃辛普森 - 亚当鲍勃琼斯

另一所学校: - 阿诺德鲍勃史密斯 - 凯茜鲍勃鲍尔斯 - 珍妮鲍勃史密斯

另一所学校: - Barney Bob Edson - Sue Bob Purdee - Alan Bob Warfield

public class School
{ 
   public int SchoolId {get; set;} 
   public string Schoolname {get; set;} 
   public int StateId {get; set;} 
} 


public class Student
{ 
   public int StudentId {get; set;}
   public int SchoolId {get; set;} 
   public string Firstname {get; set;} 
   public string Middlename {get; set;} 
   public string Lastname {get; set;} 
} 


public class SchoolViewModel
{ 
   public int SchoolId {get; set;}
   public string Schoolname {get; set;}  
   public IEnumerable<Student> Bobs { get; set; }
} 

通过使用 JOINS 执行 SELECT 获取列表将为我提供一个需要额外工作才能在 VIEW 中显示的数据集,如上图所示。我在想有一种方法可以让数据集像多维数组一样来获取嵌套的学生列表。但我没有找到这种方法的例子 - 导致我认为那不是方式......??如何以充分利用 LINQ/MVC/ViewModel 等的方式获取数据?:)

我正在尝试这样的事情 - 但不知道这是否是正确的方向 - 当我尝试设置 Bobs 时它给了我一个错误。:)

我收到如下错误:LINQ to Entities 无法识别方法 'System.Linq.IQueryable`1[stuff] GetBobs(stuff)' 方法,并且此方法无法转换为存储表达式。

  private IQueryable<SchoolViewModel> GetSchools(int StateId)
  {
        var query = from s in db.Schools
                    where s.State == StateId
                    orderby s.Schoolname
                    select new SchoolViewModel
                    {
            SchoolId = s.SchoolId,
                        Name = s.Name,
                        Bobs = GetBobs(s.SchoolId)
                    };
    var results = query;
        return results;
    }

    private IQueryable<Student> GetBobs(int id)
    {

        var query = from s in db.Students
                    where s.Middlename == 'Bob'
                    where s.SchoolId == id
                    select s;

        var results = query;
        return results;
    }
4

2 回答 2

2

好吧,您总是可以对查询部分执行此操作,我猜这就是您被绊倒的地方:

var schools = db.Schools
     .Where(x => x.State == "<Whatever>")
     .Select(x => new {
          School = x,
          Bobs = x.Where(y => y.MiddleName == "Bob")
     }).ToList();

List<Schools> schoolsView = new List<Schools>();
foreach(var x in schools)
{
     schoolsView.Add(new SchoolsViewModel(){
          //Set Properties here
          SchooldID = x.School.ID,
          SchoolName = x.School.Name,
          Students = x.Bobs.ToList() //You can project here if needed.
     };
}

return schoolsView;

然后对于您的视图,您可以通过多种方式执行此操作,但如果您有具有固定输出的具体 ViewModel,则它只是嵌套循环:

<ul>
@foreach(var m in Model)  //Assuming your model is a list of SchoolViewModels
{
     <li>@m.SchoolName
          <ul>
               @foreach(var s in m.Students)
               {
                    <li>@s.Name</li>
               }
          </ul>
     </li>
}
</ul>

你也有一些可爱的选项来做一些事情,比如String.Join(",", Model.Students)输出列表,但这取决于你。

编辑:附加说明

您还需要稍微更改模型,我不确定您使用的是哪个 EF 版本,但在 EF4.1+ 中,您可以指定导航属性以消除对显式连接条件的需要(这是正确的方法结束)。

http://msdn.microsoft.com/en-us/library/bb738520.aspx

因此,您的 Schools 模型将变为:

public class School
{ 
   public int SchoolId {get; set;} 
   public string Schoolname {get; set;} 
   public int StateId {get; set;} 
   public virtual IList<Student> Students {get; set; }
} 

然后在您的数据库配置中(如果您使用流利的配置将是:

modelBuilder.Entity<School>()
     .HasMany(x => x.Students).WithRequired();

然后你获得了做事的力量

db.Schools
    .Where(x => x.Name.Contains("Some Value"))
    .Include(x => x.Schools.Where(x => x.MiddleName.Contains("SomeValue")))
    .ToList();

这甚至使我之前的查询更加简单,而无需使用模棱两可的类型定义。

希望这个澄清有助于进一步。

于 2012-07-25T16:13:32.520 回答
1

您可以尝试这样的方法来显示数据。

顶层视图:

@model SchoolViewModel
@using (Html.BeginForm()) 
{
    <fieldset>
        @Html.EditorFor(x => x.Bobs)
        <input type="submit" value="Save" />
    </fieldset>
}

然后,您可以使用编辑器模板进行显示。在以下 URL 创建它们:~/Views/Shared/EditorTemplates/Student.cshtml

@model Student
@Html.DisplayFor(x => x.StudentID)
@Html.DisplayFor(x => x.SchoolID)
@Html.DisplayFor(x => x.FirstName)
@Html.DisplayFor(x => x.MiddleName)
@Html.DisplayFor(x => x.LastName)

然后,您可以在生成的子列表中放置您想要的任何格式。Bobs IEnumerable 中的每个 Student 都将根据您在编辑器模板中定义的规则进行渲染。

就实际查询数据库而言,我会按照这种模式创建某种存储库:

public interface IRepository<TEntity> where TEntity : class
{
    List<TEntity> FetchAll();
    IQueryable<TEntity> Query { get; }
    void Add(TEntity entity);
    void Delete(TEntity entity);
    void Save();
}  

具体实现如下:

public class SQLRepository<T> : IRepository<T> where T : class
{
    private DataContext db;
    public SQLRepository()
    {
        this.db = new TestDataContext();
    }
    public void Add(T entity)
    {
        db.GetTable(Of T)().InsertOnSubmit(entity)
    }
    public void Delete(T entity)
    {
        db.GetTable(Of T)().DeleteOnSubmit(entity)
    }
    public System.Collections.Generic.List<T> FetchAll()
    {
        return Query.ToList();
    }
    public System.Linq.IQueryable<T> Query {
        get { return db.GetTable<T>(); }
    }
    public void Save()
    {
        db.SubmitChanges()
    }
}
于 2012-07-25T16:19:59.780 回答