是否有NOSQL数据层设计模式?

sgt*_*gtz 12 .net design-patterns data-access-layer nosql

我已经看到了一些想法,而不是像创建,更新,插入,删除(CRUD)使用Get和Put.非常好.但是,我还没有看到如何处理复杂性.我被告知,"只需为您需要的每种查询类型编写一个方法".

在我开始考虑限定符(where子句)之前,大多数NOSQL似乎都没问题 - 可能会有很多变化.是否已经有一个很好的方案,以合理的方式实现限定符,只使用方法名称和参数约定?也许有某种动词/名词方案运作良好,但它本身并不是一种语言.

我不是在回答"正确"的答案......我希望我能从中学到一些思想流派.

发现RavenDB制造商的这篇博文:http://ayende.com/blog/4562/ravendb-index-management

我们可以在一个类上实现多个索引吗?

我甚至发现,有可能要序列化匿名委托http://blogs.microsoft.co.il/blogs/aviwortzel/archive/2008/06/20/how-to-serialize-anonymous-delegates.aspx 我想,如果这是可能的,他们可能会使用这样的东西.

但是,如果我们无法访问相同的程序集(例如Silverlight),该怎么办?在这里发现这篇文章:http: //ayende.com/blog/4766/accessing-ravendb-from-silverlight

IEnumerable<T>对象是客户端还是服务器端搜索的?在通过网络发送结果集之前,我们如何通过NOSQL来缩小结果集,而不将其锁定为一个唯一ID?

更新:我最终通过RavenDB向Ayende发送电子邮件.他善意回答了我的问题(如下):

你能做的就是写:

  public IEnumerable<T> FindAll(Expression<Func<T,bool>> whereClause)
  {
      return session.Query<T>().Where(whereClause).ToList();
  }
Run Code Online (Sandbox Code Playgroud)

这使用linq来计算你的意图,然后使用RavenDB的语法将查询发送到服务器.在服务器上,我们分析您的查询,查询优化器检查是否存在可以回答此查询的现有索引,如果没有,它将为您创建临时索引.

如果您足够查询该临时索引,RavenDB将使其永久化.因此,自我优化自己的运作.

您是否从"Silverlight"用例中获得了很大的帮助?

我们完全支持Silverlight.

RavenDB可以处理多个索引服务器端吗?

是.事实上,我们有一些客户有> 500个索引运行没有问题.

来自RavenDB的Ayende的信息结束

在设计的查询语言(即的FindAll /哪里/代表),蒙戈似乎通过JSON ......实现了一点这个http://www.mongodb.org/display/DOCS/Indexes 我希望我能知道更多关于它.

这听起来更接近:http://www.mongodb.org/display/DOCS/MapReduce

序列化在C#中序列化匿名委托的一个有趣的线程.这不是直接相关的...但我只是想稍微深入了解一下,所以我对潜力有了更多了解.

ole*_*sii 4

我不确定这是否适用于 NoSQL,但我使用 Raven DB 实现了通用存储库模式,这里是一个片段。

首先我定义了几个接口

internal interface ISessionProvider : IDisposable
{
    IDocumentSession OpenSession();
    void CloseSession();
}

public interface IDataAccessManager : IDisposable
{
    void Initialize();
    void OpenSession();
    void CloseSession();
}

public interface IRepository<T> where T : Entity
{
    IQueryable<T> Query();
    IEnumerable<T> Find(Func<T, bool> exp);
    T FirstOrDefault(Func<T, bool> exp);

    void Delete(T entity);
    void Add(T entity);
    void Save();

    string PutAttachment(string key, byte[] data);
    Attachment GetAttachment(string key);
    void DeleteAttachment(string key);
}
Run Code Online (Sandbox Code Playgroud)

这是一个缩短的实现

internal class SessionProvider : ISessionProvider
{
    ...

    public IDocumentSession OpenSession()
    {
        session = store.OpenSession();
        return session;
    }

    public void CloseSession()
    {
        if (session != null)
        {
            session.Dispose();
        }
    }
}

public class DataAccessManager : IDataAccessManager
{
    ...

    public void Initialize()
    {       
        store = new DocumentStore
        {
            ConnectionStringName = ConnectionString
        };
        store.Initialize();
        store.DatabaseCommands.EnsureDatabaseExists(dbName);

        provider = new SessionProvider(store);
    }

    public void OpenSession()
    {
        session = provider.OpenSession();
    }

    public void CloseSession()
    {
        provider.CloseSession();
    }
}


public class Repository<T> : IRepository<T> where T : Entity
{
    ...

    public IEnumerable<T> Find(Func<T, bool> exp)
    {
        return AsQuaribale().Where(exp);
    }

    public void Add(T entity)
    {
        session.Store(entity);
    }

    public void Save()
    {
        session.SaveChanges();
    }

    public string PutAttachment(string key, byte[] data)
    {
        Guid? etag = null;
        var metadata = new RavenJObject
        {
            {"owner", Thread.CurrentPrincipal.Identity.Name},
            {"filename", key}
        };
        session.Advanced.DatabaseCommands.PutAttachment(key, etag, data, metadata);

        return key;
    }

    public Attachment GetAttachment(string key)
    {
        return session.Advanced.DatabaseCommands.GetAttachment(key);
    }

    private IQueryable<T> AsQuaribale()
    {
        return session.Query<T>().Customize(x => x.WaitForNonStaleResultsAsOfNow(Timeout));
    }
}
Run Code Online (Sandbox Code Playgroud)

使用示例

private void SendData()
{
    try
    {
        dataManager.OpenSession();
        repository = new Repository<MyDomainType>();

        ...

        foreach (string path in paths)
        {           
            //read file to memory
            byte[] data = File.ReadAllBytes(path);
            string fName = Path.GetFileName(path);
            myDomainType.Name = fName;

            //save data in memory and metadata to the database
            string key = repository.PutAttachment(
                myDomainType.Id.ToString(), data);

            repository.Add(myDomainType);
        }

        repository.Save();
    }
    catch (Exception ex)
    {
        AppManager.LogException(ex);
    }
    finally
    {
        dataManager.CloseSession();
        dataManager.Dispose();      
    }
}
Run Code Online (Sandbox Code Playgroud)

create 的示例测试,使用 Find (FirstOrDefault) 方法进行断言

[Test]
public void CreateValueTest()
{
    var repository = ContainerService.Instance.Resolve<IRepository<DummyType>>();
    var expected = new DummyType();
    repository.Add(expected);
    repository.Save();
    DummyType actual = repository.FirstOrDefault(item => item.Id == expected.Id);

    Assert.IsTrue(expected == actual);
}
Run Code Online (Sandbox Code Playgroud)