【问题标题】:Ensuring the same output for a given input (pure function)?确保给定输入的输出相同(纯函数)?
【发布时间】:2017-07-17 06:02:33
【问题描述】:

在我尝试以更实用的方式进行编程的过程中,我提出了以下静态函数:

public static class BaseService
{
    public static T EntityGet<T>(Guid id, XrmServiceContext xrmServiceContext) where T : Entity
    {
        return xrmServiceContext.CreateQuery<T>().Single(query => query.Id == id);
    }
}

我们如何确保它是确定性的并且总是为指定的输入返回相同的值?

请注意,XrmServiceContext 是一个存储库,可能会根据连接是打开还是关闭而抛出。

我们是否应该将返回类型包装到 Maybe 中? :

public static Maybe<T> EntityGet<T>(Guid id, XrmServiceContext xrmServiceContext) where T : Entity
{
    return xrmServiceContext.CreateQuery<T>().Single(query => query.Id == id).ToMaybe();
}

这样我们可以100%确定返回值。

问题:Maybe 更改之后,我们现在是否可以拥有完全确定的行为,无论存储库是启动还是关闭?

【问题讨论】:

  • 如果数据库关闭,Single 会抛出异常,因此执行不会到达 ToMaybe。另外,我不确定任何调用数据库(外部存储)的函数在严格意义上如何是纯粹的。
  • 我不知道。我们可以得出结论,你不能有一个纯函数来进行数据库调用吗?

标签: c# .net visual-studio functional-programming dynamics-crm-2011


【解决方案1】:

这段代码 xrmServiceContext.CreateQuery&lt;T&gt;().Single(query =&gt; query.Id == id).ToMaybe(); 存在问题,因为如果没有任何内容与查询匹配,IQueryable.Single 将抛出 InvalidOperationException

你需要在这里使用IQueryable.SingleOrDefault来避免异常并返回一个空值(假设你想要一个空值。)你仍然需要将它包装在一个Try/Catch中来处理诸如数据库中断、超时、等等。设置 Try 成本很低,但 Catch 可能很昂贵,因此我们希望避免将其用于逻辑。通过使用SingleOrDefault,您可以处理最常见的异常,因为 Id 不存在,并允许 Catch 仅处理意外(网络故障等)

public static T EntityGet<T>(Guid id, OrganizationServiceContext xrmServiceContext) where T : Entity
{           
    try
    {
        return xrmServiceContext.CreateQuery<T>().SingleOrDefault(query => query.Id == id);
    }
    catch (Exception)
    {
        // Log the exception or this could create a debugging nightmare down the road!!!
        return default(T);
    }            
}

如果您想使用 Functional.Maybe 库编写它,您可以:

public static Maybe<T> EntityGet<T>(Guid id, OrganizationServiceContext xrmServiceContext) where T : Entity
{
    try
    {
        return xrmServiceContext.CreateQuery<T>().SingleOrDefault(query => query.Id == id).ToMaybe();
    }
    catch (Exception)
    {
        // Log the exception or this could create a debugging nightmare down the road!!!
        return Maybe<T>.Nothing;
    }
}

【讨论】:

    【解决方案2】:

    您可以将调用包装为 try catch,并在最后始终返回可能,但我不确定这是我推荐的操作过程。这意味着检索实体的每个调用站点都必须处理检查可能,然后决定如果失败该怎么办。

    在这种情况下,而不是追求“完美” 我会接受错误发生,它们会冒泡。此外,由于您正在处理数据库,因此无法保证该值将存在于数据库中,或者它将是相同的值(未更新)。

    【讨论】:

      猜你喜欢
      • 2019-07-26
      • 1970-01-01
      • 2021-07-21
      • 1970-01-01
      • 2015-05-30
      • 2011-04-10
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多