是否有 NOSQL 數據層設計模式?
我已經看到了一些類似的想法,而不是像 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); }