实体框架何时创建自定义DTO?

时间:2013-03-10 04:49:53

标签: ef-code-first entity-framework-5

我的应用程序中有一个非常简单的存储库模式,但现在我有一个无法解决的问题,我需要返回Code First Model和一些额外的数据。见下文。

public IEnumerable<User> GetUsersWithinLocation(DbGeography geography)

我真正希望在返回模型中包含的是用户实例和距地理的距离(以英里或其他为单位)。

以下是我看到的选项:

选项1:我可以返回用户对象列表,没有距离,在前端重新计算第二次,并避免使我的数据模型混乱,但似乎有点多余..而且,在某些情况下这可能是不可能的,我只是觉得这种做法是错误的。

选项2:另一种选择是创建一个新的DTO,它由User或者UserDistance对象组成或继承。这会给我我需要的一切,但是我会为此创建一个新的存储库吗?如果每个模型类型返回的数据有很多变化,我可以看到这在大型应用程序中维护有点不守规矩。

选项3:实现某种动态的ExtraData ViewBag图层,我可以随意传递额外的数据和DTO。这将在我的图层之间创建更紧密的耦合,因为必须知道名称。我也不喜欢这种方法。

非常感谢任何指导。

3 个答案:

答案 0 :(得分:1)

这里是摆脱对Distance的双重调用的方法:

public IDictionary<User, double?> GetUsersWithinByLocation(DbGeography geography)
{
    return this.Query.Select(x => new KeyValuePair<User, double?>(x, x.Address.Location.Distance(geography)))
                     .OrderBy(kvp => kvp.Value)
                     .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}

你可以做的另一件事,我认为更好一点是改变你的返回类型,这样你就可以做一个更简单/更快的LINQ查询,这里是代码:

public IEnumerable<KeyValuePair<User, double?>> GetUsersWithinByLocation(DbGeography geography)
{
    return this.Query.Select(x => new KeyValuePair<User, double?>(x, x.Address.Location.Distance(geography)))
                     .OrderBy(kvp => kvp.Value);
}

这种方法可以与KeyValuePair<T1, T2>一样使用,也可以Tuple<T1, T2>使用。

请注意,在这两种情况下,我所做的是首先“存储”Distance的计算,然后通过{{1}中Value的{​​{1}}属性访问它子句。

希望这会有所帮助;)

答案 1 :(得分:0)

这个怎么样?这里有什么问题吗?

public IDictionary<User, double?> GetUsersWithinByLocation(DbGeography geography)
{
    return this.Query.OrderBy(x=>x.Address.Location.Distance(geography))
          .ToDictionary(x => x, x => x.Address.Location.Distance(geography));
}

主要问题是我们两次运行这个距离函数,有没有办法解决这个问题?

答案 2 :(得分:0)

我经常问自己一个不同的问题:我可以使用域对象进行数据传输吗?几乎没有答案是肯定的。为什么会这样?在许多情况下,UI切片通过域模型并想要一部分和一部分。 (几乎)总是涉及视图模型。大多数情况下,视图模型都经过验证。

对我来说:选项2 。但是存储库不应该提供视图模型。它应该是位于存储库和视图(控制器,如果您在mvc中)之间的服务层,并且编排存储库调用以收集视图模型的数据。存储库在内部公开IQueryable,服务组成对这些IQueryables的查询并公开IEnumerable