【问题标题】:Entity Framework - joining nulls - NullReferenceException was unhandled by user code实体框架 - 加入空值 - 用户代码未处理 NullReferenceException
【发布时间】:2009-12-24 22:57:19
【问题描述】:

我正在编写一个 asp.net mvc 应用程序来学习实体框架,但我遇到了一个我不知道如何处理的问题。为简单起见,我们采用以下表结构:

Movie  
ID (int, not null, auto increment)  
Name (varchar)  
GenreID (int)

和

Genre  
ID (int, not null, auto increment)  
Name (varchar)

Movie.GenreID 是对 Genre.ID 的 FK 引用

我在 VS 2008 中使用可视化设计器查看了所有表格,并尝试了以下 Linq 查询:

IEnumerable<Movie> movieList = from f in dataContext.MovieSet.Include("Genre").ToList();

我可以使用以下方法在视图中输出数据:

<%= Html.Encode( movieList.Genre.Name ) %>

一切正常,直到我在电影表中有一个具有空类型 ID 的项目。我可以对这个查询做些什么来使它仍然能够输出(在适用时将其留空)还是我做错了什么?

【问题讨论】:

    标签: asp.net asp.net-mvc entity-framework entity-relationship


    【解决方案1】:

    问题是movieList.Genre 为空,您无法访问null 对象的Name 属性。

    你可以写&lt;%= Html.Encode(movieList.Genre == null ? String.Empty : movieList.Genre.Name) %&gt;来解决这个问题。

    如果您不希望您的视图如此冗长,您可以将GenreName 属性添加到Movie 实体类并将空检查移到那里。

    【讨论】:

    • 有趣的是它将对象保留为空(因此不允许访问其任何属性)。我会假设它的所有方法都可以访问,而它们的值中没有任何内容。 (就像我输入“选择 m.*, g.N​​ame as GenreName from movies m left join genres g on g.ID = m.GenreID”并返回了一个记录集,我仍然可以调用 GenreName 并得到一个空响应,连接没有发生也不例外)这消除了错误,但我希望避免任何形式的视图检查。
    • 我同意“movieList.Genre.Name”语法非常冗长,但我可以想到我将来可能希望能够拥有该功能的原因(尽管显然没有真正需要在这个例子中,更多的是试图了解所有 EF/Linq 能够做什么)。我注意到,如果在我拨打电话以获取我的查询后,如果我添加“if (movie.Genre == null)movie.Genre = new Genre();”在我返回我的电影对象之前,它的行为几乎与我希望的一样。有没有办法绕过检查每个属性是否为空的需要?
    【解决方案2】:

    这可能比.Include("")更具可读性

    from f in dataContext.MovieSet
    select new
        {
           Name = f.Name,
           Genre = f.Genre // This effectively performs a join.
           ...
        }
    

    你也可以这样检查问题:

    from f in dataContext.MovieSet
    select new
        {
           Name = f.Name,
           GenreName = f.Genre == null ? "" : f.Genre.Name
           ...
        }
    

    这为您提供了更大的灵活性,例如:

    from f in dataContext.Genres
    select new
        {
            Name = f.Name
            Movies = from movie in f.Movies
                     where movie.Duration > 240
                     select movied
        }
    

    【讨论】:

    • 这非常有用,因为我是 Linq 和 EF 的新手。有没有办法像您在上面发布的查询那样返回或可以转换为当我将表模式导入 EF 时创建的强类型类?
    • 针对您的第二个示例,如果我将“选择新”部分更改为:select new { f, Genre = (f.Genre == null) ? new Genre() : f.Genre } 但我仍然遇到上面的类型转换问题。再次感谢您的回复 - 我非常感谢您在上面给我的示例。
    • 你可以像这样返回强类型类。唯一需要记住的是,Linq 不支持带参数的构造函数。而是使用对象初始化器语法:select new Movie { Name = f.Name, GenreName = f.Genre == null ? "" : g.Genre.Name };
    猜你喜欢
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    相关资源
    最近更新 更多