【问题标题】:Load a DataGridView from LINQ to SQL query从 LINQ 加载 DataGridView 到 SQL 查询
【发布时间】:2018-06-02 22:23:44
【问题描述】:

我从 LINQ 查询加载数据网格视图时出错。

我正在查询以从 3 个表中加载数据,但我总是收到“无法将 List 隐式转换为 IQueryable。我知道存在强制转换,但无法弄清楚。

因此,首先,我在表单中添加了一个类,该类将具有我希望加入的每一行的值作为属性:

public class ListofModuleUser
{
    public string User { get; set; }
    public string Modulo { get; set; }
    public bool Read { get; set; }
    public bool Write { get; set; }
    public bool Create { get; set; }
    public bool Delete { get; set; }
    public bool Navigate { get; set; }
}

其次,我正在查询并希望返回一个列表以便能够填充我的 datagridview:

public IQueryable<ListofModuleUser> LoadData()
{
    var ctx = new JEntities();
    var fillusers = (from mu in ctx.tblModuloUsers.AsQueryable()
                     join u in ctx.tblUsers on mu.UserID equals u.UserID
                     join m in ctx.tblModuloes on mu.ModuloID equals m.ModuloID
                     select new
                     {
                         User = u.Username,
                         Modulo = m.Moduloname,
                         Read = mu.CanRead,
                         Write = mu.CanWrite,
                         Create = mu.CanCreate,
                         Delete = mu.CanDelete,
                         Navigate = mu.CanNavigate
                     }).ToList();

    return fillusers; //---> Obviously the error occours here! 
}

然后,在 Load 事件中,我得到我的列表并填充我的 datagridview:

private void MapUserToModulos_List_Load(object sender, EventArgs e)
{
     usersmodules_datagrid.DataSource = LoadData();
}

谁能帮我弄清楚我必须使用哪种演员表,因为我已经尝试了所有可能的演员表(ToList、Array、AsEnumerable、AsQueryable...)

【问题讨论】:

    标签: c# winforms linq


    【解决方案1】:

    您的方法声称返回IQueryable&lt;T&gt;

    public IQueryable<ListofModuleUser> LoadData()
    

    但你试图返回一个List&lt;T&gt;

    var fillusers = ....ToList();
    return fillusers;
    

    如果要返回一个列表,改变方法的返回类型:

    public IList<ListofModuleUser> LoadData()
    

    或者,如果您想返回 IQueryable,请从您的 LINQ 查询中删除 .ToList()


    另外,你的返回类型是一个特定的类:

    ListofModuleUser
    

    但是你正在查询一个匿名对象:

    select new
    {
        User = u.Username,
        Modulo = m.Moduloname,
        Read = mu.CanRead,
        Write = mu.CanWrite,
        Create = mu.CanCreate,
        Delete = mu.CanDelete,
        Navigate = mu.CanNavigate
    }
    

    你必须查询到正确的类型:

    select new ListofModuleUser
    {
        User = u.Username,
        Modulo = m.Moduloname,
        Read = mu.CanRead,
        Write = mu.CanWrite,
        Create = mu.CanCreate,
        Delete = mu.CanDelete,
        Navigate = mu.CanNavigate
    }
    

    旁注:ListofModuleUser 是单个对象的一个​​非常不直观的名称。您正在创建的基本上称为“模块用户列表列表”。也许这个类应该叫ModuleUser

    【讨论】:

      【解决方案2】:

      您的代码中有 3 个重要问题。

      1. 首先,IQueryable&lt;T&gt; 表示必须执行的查询并将结果加载到内存中。您不希望这样,结果应该被具体化,并且客户端不应该知道查询。所以,把你的返回类型改成IEnumerable&lt;T&gt;

        public IEnumerable<ListofModuleUser> LoadData()
        
      2. 您的方法声称返回 ListofModuleUser 但您正在投影到一个匿名对象,请将其更改为返回实际类:

        select new ListofModuleUser
        {
            User = u.Username,
            Modulo = m.Moduloname,
            Read = mu.CanRead,
            Write = mu.CanWrite,
            Create = mu.CanCreate,
            Delete = mu.CanDelete,
            Navigate = mu.CanNavigate
        }
        
      3. 您没有释放您正在创建的DbContext 实例,这很容易变成内存泄漏。您应该始终在 IDisposable 对象周围使用 using 语句:

        using (var ctx = new JEntities())
        {
            ...
        }
        

      将所有这些放在一起,您的代码应如下所示:

      public IEnumerable<ListofModuleUser> LoadData()
      {
          using (var ctx = new JEntities())
          {
              return (from mu in ctx.tblModuloUsers.AsQueryable()
                      join u in ctx.tblUsers on mu.UserID equals u.UserID
                      join m in ctx.tblModuloes on mu.ModuloID equals m.ModuloID
                      select new ListofModuleUser
                      {
                          User = u.Username,
                          Modulo = m.Moduloname,
                          Read = mu.CanRead,
                          Write = mu.CanWrite,
                          Create = mu.CanCreate,
                          Delete = mu.CanDelete,
                          Navigate = mu.CanNavigate
                       })
                       .ToList();
          }
      }
      

      我还建议将 ListofModuleUser 重命名为 ModuleUser,因为该类代表单个模块用户。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 1970-01-01
        • 2016-01-31
        相关资源
        最近更新 更多