簡體   English   中英

如何設置內存存儲庫

[英]How to set up an in-memory repository

我有以下課程:

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<TestEntity>(object id)應該能夠查詢所有存儲的TestEntity實例並找到具有匹配Id屬性的實例,但是我無法直接定義TestEntity對象的集合,因為存儲庫不知道什么類型我正在喂它直到運行時間。
  • 我需要為Query()方法支持LINQ to Objects。 假設我可以想出一個存儲對象的好方法,這應該像返回存儲對象AsQueryable()的數組一樣簡單。

您如何存儲對象以滿足上述要求?

基礎知識很簡單:

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<T> GetAll<T>(string queryName) ,事情變得復雜。

您可以在測試中使用基於SQLite的存儲庫實現。

通過Anton的回答,我能夠修復自己的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

我會使用NHibernate為內存中的SqlLite數據庫配置。 您可以測試您的真實代碼,並確保一切正常。 為Repository編寫模擬可能很難,如果更改IRepository接口,則必須重新實現InMemoryRepository

對我來說,擁有NHibernate的一大好處是可以在內存數據庫中進行測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM