实现“实体框架”中的“每个对象一个实例”

时间:2012-05-03 10:06:42

标签: .net entity-framework design-patterns

我编写了一个分层的.NET 4.0应用程序。数据层使用实体框架实现,并且存在向调用者(即业务层)提供实体实例的存储库。当实体框架被要求某个实体两次(例如通过密钥)时,它将返回相同的实例,因此我对该实体所做的更改将反映在使用该实体的其他位置。它不是真正的缓存功能,因为没有过期策略,并且性能似乎没有得到很大改善,因为实体框架仍然会查询数据库,至少在很多情况下。关键是要确保每个实体只有一个实例(每个上下文)。

在业务层中,实体映射到业务对象,这些业务对象的结构可能与实体不同。同样,与数据层中的存储库一样,存在集中访问点以获取业务对象的实例。我现在的目标是,在业务层中具有实体框架提供的相同功能,意味着“始终为特定对象返回相同的实例”。我想确保,对应用程序中任何位置的某个业务对象的每次访问都可以在同一个实例上运行。

开始编辑

语境意识很重要!与实体框架类似,每个业务对象实例的唯一性应该在每个上下文基础上提供,而不是严格地在整个应用程序上提供。在业务层中还有上下文的概念,每个上下文都应该有自己的每个业务对象的实例。在使用上下文的任何地方都应该重用此实例。

此外,我正在寻找一种解决方案,不需要为每个业务对象类实现。可能有数百个。我更喜欢框架代码中的解决方案,它对于实现存储库的人来说尽可能透明。实体框架本身也不了解特定的实体类型,实体框架仍然能够为实体模型开发人员提供透明的这种功能。

结束编辑

我的问题是:

  • 这个“每个对象只有一个实例”的行为是否有名称?什么是Google搜索字词?
  • 是否有参考,指南或最佳实践,或者是否存在处理此问题的设计模式?
  • .NET中的类是否有助于编写此类功能,甚至完全提供它?

谢谢和问候, 彼得。

2 个答案:

答案 0 :(得分:0)

是的它有一个名字。它被称为Identity Map模式,通常它只是对象键/对象对的字典。

答案 1 :(得分:0)

以下是可以为您指明方向的示例。考虑你有类User(有私人Id设置器):

public class User
{
    public int Id { get; private set; }
    public string Name { get; set; }
}

将所有用户存储在存储库中(我使用Dictionary进行快速访问):

public class UserRepository
{
    private static UserRepository _instance = new UserRepository();
    Dictionary<int, User> _users = new Dictionary<int, User>();

    private UserRepository()
    {
    }

    public static UserRepository Instance
    {
        get { return _instance; }
    }

    public IEnumerable<User> FindAll()
    {
        return _users.Values;
    }

    public User FindById(int id)
    {
        return _users[id];
    }

    public void SaveOrUpdate(User user)
    {
        if (user.Id == 0)
        {
            int nextId = _users.Count + 1;
            PropertyInfo id = typeof(User).GetProperty("Id");
            id.SetValue(user, nextId, null);
            _users.Add(user.Id, user);
            return;
        }

        _users[user.Id] = user;
    }
}

这里有趣的是:

  • 存储库是单例。因为您只需要存在一个用户集合/词典
  • 在程序中创建用户时,其ID将为0.因此,您可以定义新用户或现有用户
  • 反射用于设置私有财产价值
  • 单例实现和下一代ID生成很简单(仅用于快速示例)

现在你可以做到:

UserRepository repository = UserRepository.Instance;
repository.SaveOrUpdate(new User() { Name = "Joe" });

在其他地方,您可以获得相同的用户实例:

var otherRepository = UserRepository.Instance;
User user = otherRepository.FindById(1);