0

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

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

开始编辑

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

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

结束编辑

我的问题是:

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

谢谢和问候,彼得。

4

2 回答 2

0

是的,它有一个名字。它被称为身份映射模式,通常它只是对象键/对象对的字典。

于 2012-05-03T10:13:41.270 回答
0

这是可以为您提供方向的示例。考虑您有类用户(具有私有 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);
于 2012-05-03T10:37:25.690 回答