【问题标题】:What do I return when there is no such row in database?当数据库中没有这样的行时,我返回什么?
【发布时间】:2018-10-27 07:42:23
【问题描述】:

我正在使用 Entity 框架,并且我有一个 Repository 类,它使用 dbContext 对象进行所有数据提取。

目前有一个方法叫

public MovieDetails FindSingle(int? id)
{
    using (MovieContext dbContext = new MovieContext())
    {
        var newMovieDetails = dbContext.Movies.FirstOrDefault(x => x.MovieID == id);
        if (newMovieDetails == null)
        {
            throw new Exception();
        }
        var MappedDetails = new MovieDetails
        {
            MovieID = newMovieDetails.MovieID,
            MovieName = newMovieDetails.MovieName
        };
        return MappedDetails;
    }
}

目前,当程序在数据库中找到匹配项时,它会转换为Data Object Transfer-object 当我尝试搜索数据库中不存在的电影时,我收到错误消息。有没有办法可以返回一个类型,说数据库中不存在这样的行?还是应该只返回一个空对象?

【问题讨论】:

  • 你可以返回 null 而不是抛出异常
  • 返回一个空对象对我来说似乎是个坏主意。不能直接回null吗?
  • return null 并检查返回的位置,如果为 null,则显示不存在此类电影的消息。

标签: c# entity-framework error-handling


【解决方案1】:

你可以使用这个包:https://github.com/vkhorikov/CSharpFunctionalExtensions#make-nulls-explicit-with-the-maybe-type

然后你可以设置为return:

public Maybe<MovieDetails> FindSingle(int? id)

所以你在哪里调用你的函数,你知道它可能是空的。您必须检查:if (customerOrNothing.HasNoValue)

希望对你有帮助!

【讨论】:

    【解决方案2】:

    对这样的事情使用异常是个坏主意。
    异常适用于异常情况,即您无法在代码中控制的情况,例如网络错误和 I/O 权限违规。
    这种事是什么Eric Lippert would call a vexing exception

    烦恼异常是不幸的设计决策的结果。令人烦恼的异常是在完全非异常的情况下抛出的,因此必须一直被捕获和处理。

    一个令人烦恼的异常的经典例子是Int32.Parse,如果你给它一个不能被解析为整数的字符串,它就会抛出。但是这种方法 99% 的用例是转换用户输入的字符串,这可能是任何旧事物,因此解析失败绝不是例外。更糟糕的是,如果不自己实现整个方法,调用者就无法提前确定他们的参数是否错误,在这种情况下,他们不需要一开始就调用它。

    这个不幸的设计决定非常令人烦恼,当然框架团队在此后不久就实施了TryParse,它做了正确的事情。

    如果MappedDetails 是引用类型,则最好在未找到时返回null
    如果是值类型,请将方法更改为返回MovieDetails? 并返回null

    我还建议您将方法名称从 FindSingle 更改为 GetMovieDetails 或类似的名称。
    这样,当您在 6 个月后查看代码并看到如下内容时:

    ....
    var details = GetMovieDetails(id);
    ....
    

    您可以立即知道该方法的实际作用,与

    ....
    var details = FindSingle(id);
    ....
    

    这基本上什么也没告诉你。

    【讨论】:

    • 值类型和引用类型有什么区别?
    • 这个方法被命名为 FindSingle 因为一个接口。
    • 有一些方法可以解决这个问题,例如显式接口实现和显式接口实现执行的正确命名的方法......或者只是更改接口。否则,请注意使用此方法的代码:MovieDetails? details = FindSingle(MovieId); 也足够可读。
    猜你喜欢
    • 2020-05-18
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-15
    • 1970-01-01
    • 2020-03-12
    • 2022-10-20
    相关资源
    最近更新 更多