如何设置内存存储库

发布于 2024-10-29 22:12:18 字数 1355 浏览 0 评论 0原文

我有以下类:

public class InMemoryRepository : IRepository
{
    public void Add(object entity)
    {
        throw new NotImplementedException();
    }

    public void Attach(object Entity)
    {
        throw new NotImplementedException();
    }

    public T Get<T>(object id)
    {
        throw new NotImplementedException();
    }

    public IList<T> GetAll<T>(string queryName)
    {
        throw new NotImplementedException();
    }

    public IList<T> GetAll<T>()
    {
        throw new NotImplementedException();
    }

    public IQueryable<T> Query<T>()
    {
        throw new NotImplementedException();
    }

    public void Remove(object entity)
    {
        throw new NotImplementedException();
    }

    public void Save(object entity)
    {
        throw new NotImplementedException();
    }
}

我们的默认存储库实现使用 NHibernate 作为后备存储,但我想实现它的内存版本,这样我就可以对域对象进行原型设计,而无需创建后备 SQL 数据库。假设所有对象都有一个 Id 属性作为主键,您将如何为此实现通用内存存储?

我很难解决一些关键点:

  • 存储库方法本身是通用的,因此我需要某种机制来自动存储和引用不同类型。 Get(object id) 应该能够查询 TestEntity 的所有存储实例并找到具有匹配 Id 属性的实例,但我无法直接定义 TestEntity 对象的集合,因为直到运行时,存储库才会知道我正在向它提供什么类型。
  • 我需要支持 LINQ to Objects 的 Query() 方法。假设我可以想出一种存储对象的好方法,这应该像返回存储对象的数组 AsQueryable() 一样简单。

您将如何存储对象来满足上述要求?

I have the following class:

public class InMemoryRepository : IRepository
{
    public void Add(object entity)
    {
        throw new NotImplementedException();
    }

    public void Attach(object Entity)
    {
        throw new NotImplementedException();
    }

    public T Get<T>(object id)
    {
        throw new NotImplementedException();
    }

    public IList<T> GetAll<T>(string queryName)
    {
        throw new NotImplementedException();
    }

    public IList<T> GetAll<T>()
    {
        throw new NotImplementedException();
    }

    public IQueryable<T> Query<T>()
    {
        throw new NotImplementedException();
    }

    public void Remove(object entity)
    {
        throw new NotImplementedException();
    }

    public void Save(object entity)
    {
        throw new NotImplementedException();
    }
}

Our default repository implementation uses NHibernate for the backing store, but I'd like to implement an in-memory version of it so I can prototype the domain objects without having to create a backing SQL database. Assuming the convention that all objects have an Id property as the primary key, how would you implement a generic memory store for this?

Some key points I'm having a hard time addressing:

  • The repository methods themselves are generic, so I need some mechanism for automatically storing and referencing different types. Get<TestEntity>(object id) should be able to query all stored instances of TestEntity and find the one with the matching Id property, but I can't define a collection of TestEntity objects directly, as the repository won't know what types I'm feeding it until runtime.
  • I need to support LINQ to Objects for the Query() method. Assuming I can come up with a decent way to store the objects, this should be as simple as returning an array of stored objects AsQueryable().

How would you store the objects to meet the above requirements?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蹲在坟头点根烟 2024-11-05 22:12:18

基础知识很简单:

public class InMemoryRepository : IRepository
{
    private readonly IList<object> entities = new List<object>();

    public T Get<T>(object id)
    {
        return entities.OfType<T>.SingleOrDefault(e => e.ID == id);
    }

    public IList<T> GetAll<T>()
    {
        return entities.OfType<T>.ToList();
    }

    public IQueryable<T> Query<T>()
    {
        return GetAll<T>.AsQueryable();
    }
}

但是,一旦涉及 public IList, GetAll(string queryName),事情变得复杂。

您可能可以使用基于 SQLite 的存储库实现来进行测试。

Basics are simple:

public class InMemoryRepository : IRepository
{
    private readonly IList<object> entities = new List<object>();

    public T Get<T>(object id)
    {
        return entities.OfType<T>.SingleOrDefault(e => e.ID == id);
    }

    public IList<T> GetAll<T>()
    {
        return entities.OfType<T>.ToList();
    }

    public IQueryable<T> Query<T>()
    {
        return GetAll<T>.AsQueryable();
    }
}

However, as soon as it comes to public IList<T> GetAll<T>(string queryName), things get complicated.

Potentially you can resort to an SQLite-based repository implementation for your tests.

变身佩奇 2024-11-05 22:12:18

我会选择为 内存 SqlLite 数据库 配置 NHibernate。然后您可以测试您的真实代码并确保一切正常。为 Repository 编写模拟可能很困难,如果更改 IRepository 接口,则必须重新实现 InMemoryRepository。

对我来说,使用 NHibernate 的一大好处是可以使用内存数据库进行测试。

I would go with NHibernate configured for in-memory SqlLite database. You can test then your real code and be sure that everything works correct. Writing mock for Repository can be hard and if you change IRepository interface you will have to reimplement you InMemoryRepository.

For me one of big benefits of having NHibernate is the possibility for using in memory database for testing.

完美的未来在梦里 2024-11-05 22:12:18

通过安东的回答,我能够修复我自己的 InMemoryRepository。我已经修改它以匹配问题中的类:

private readonly ConcurrentDictionary<Type, List<object>> ObjectList = new ConcurrentDictionary<Type, List<object>>();

public int Add<T>(T obj) where T : IIdentifier
{
    // instantiate if list does not exist for this object type
    if (!ObjectList.ContainsKey(typeof (T)))
        ObjectList[typeof(T)] = new List<object>();

    // get id
    var id = GetId<T>() + 1;

    // add object to list
    obj.Id = id;
    ObjectList[typeof(T)].Add(obj);

    return id;
}

public void Attach<T>(T obj) {
    // do not need to do anything
}

public T Get<T>(int id) where T : class, IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof (T)))
        return null;

    return ObjectList[typeof(T)].OfType<T>().FirstOrDefault(n => n.Id == id);
}

public List<T> GetAll<T>(Func<T, bool> predicate) where T : new()
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return null;

    return ObjectList[typeof(T)].OfType<T>().Where(predicate).ToList();
}

public List<T> GetAll<T>()
{
    return ObjectList[typeof(T)].OfType<T>.ToList();
}

public IQueryable<T> Query<T>()
{
    return GetAll<T>.AsQueryable();
}

public int Remove<T>(int id) where T : IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return 0;

    // find object with matching id
    for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
        if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == id)
        {
            ObjectList[typeof(T)].RemoveAt(i);
            return id;
        }

    // object not found
    return 0;
}

public int Save<T>(T obj) where T : IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return 0;

    // find object with matching id
    for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
        if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == obj.Id)
        {
            ObjectList[typeof (T)][i] = obj;
            return obj.Id;
        }

    // object not found
    return 0;
}

#region Helper methods

private int GetId<T>() where T : IIdentifier
{
    return ObjectList[typeof(T)].Count == 0 ? 0 : ObjectList[typeof(T)].OfType<T>().Last().Id;
}

#endregion

With Anton's answer I was able to fix my own InMemoryRepository. I have modified it to match the class in the question:

private readonly ConcurrentDictionary<Type, List<object>> ObjectList = new ConcurrentDictionary<Type, List<object>>();

public int Add<T>(T obj) where T : IIdentifier
{
    // instantiate if list does not exist for this object type
    if (!ObjectList.ContainsKey(typeof (T)))
        ObjectList[typeof(T)] = new List<object>();

    // get id
    var id = GetId<T>() + 1;

    // add object to list
    obj.Id = id;
    ObjectList[typeof(T)].Add(obj);

    return id;
}

public void Attach<T>(T obj) {
    // do not need to do anything
}

public T Get<T>(int id) where T : class, IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof (T)))
        return null;

    return ObjectList[typeof(T)].OfType<T>().FirstOrDefault(n => n.Id == id);
}

public List<T> GetAll<T>(Func<T, bool> predicate) where T : new()
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return null;

    return ObjectList[typeof(T)].OfType<T>().Where(predicate).ToList();
}

public List<T> GetAll<T>()
{
    return ObjectList[typeof(T)].OfType<T>.ToList();
}

public IQueryable<T> Query<T>()
{
    return GetAll<T>.AsQueryable();
}

public int Remove<T>(int id) where T : IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return 0;

    // find object with matching id
    for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
        if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == id)
        {
            ObjectList[typeof(T)].RemoveAt(i);
            return id;
        }

    // object not found
    return 0;
}

public int Save<T>(T obj) where T : IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return 0;

    // find object with matching id
    for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
        if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == obj.Id)
        {
            ObjectList[typeof (T)][i] = obj;
            return obj.Id;
        }

    // object not found
    return 0;
}

#region Helper methods

private int GetId<T>() where T : IIdentifier
{
    return ObjectList[typeof(T)].Count == 0 ? 0 : ObjectList[typeof(T)].OfType<T>().Last().Id;
}

#endregion
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文