Dot-Net

是否有 NOSQL 數據層設計模式?

  • February 12, 2016

我已經看到了一些類似的想法,而不是像 Create、Update、Insert、Delete (CRUD) 使用 Get 和 Put。那挺好的。但是,我還沒有看到太多關於如何處理複雜性的內容。有人告訴我,“只需為您需要的每種查詢類型編寫一個方法”。

在我開始考慮限定符(where 子句)之前,大多數 NOSQL 對我來說似乎都不錯——可能會有很多變化。是否已經有一個很好的方案來以合理的方式實現限定符,只使用方法名稱和參數約定?也許有某種動詞/名詞方案效果很好,但它本身並不是一種語言。

我不追求“正確”的答案……我希望有一些我可以學習的思想流派。

從 RavenDB 的製造商處找到這篇博文:http: //ayende.com/blog/4562/ravenb-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-ravenb-from-silverlight

對像是在IEnumerable<T>客戶端還是伺服器端搜尋的?我們在 NOSQL 中的伺服器端在通過網路發送回之前縮小結果集的範圍有多具體,而不會將其鎖定到一個唯一的 ID?

更新:我最終從 RavenDB 給 Ayende 發送了電子郵件。他友好地回答了我的問題(如下):

你可以做的是寫:

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

這使用 linq 來確定您的意圖,然後使用 RavenDB 的語法將查詢發送到伺服器。在伺服器上,我們分析您的查詢,查詢優化器檢查是否存在可以回答此查詢的現有索引,如果沒有,它將為您創建一個臨時索引。

如果您對該臨時索引進行足夠多的查詢,RavenDB 將使其永久化。因此,自我優化自己的操作。

您對“來自 Silverlight”案例的了解是否很遠?

我們完全支持 Silverlight。

RavenDB 可以處理多個索引伺服器端嗎?

是的。事實上,我們有一些客戶執行超過 500 個索引而沒有問題。

來自 RavenDB 的 Ayende 的資訊結束

在設計查詢語言(即 FindAll/where/delegate)時,mongo 似乎通過 JSON 實現了一些… http://www.mongodb.org/display/DOCS/Indexes 我希望我了解更多關於它的資訊。

這聽起來更接近:http ://www.mongodb.org/display/DOCS/MapReduce

一個關於在 C# 中序列化序列化匿名委託的有趣執行緒。這不是直接相關的……但我只是想稍微了解一下引擎蓋,以便我了解更多關於潛力的資訊。

我不確定這是否適用於 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);
}

這是一個縮短的實現

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));
   }
}

使用範例

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();      
   }
}

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);
}

引用自:https://stackoverflow.com/questions/6885206