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#中序列化匿名委托的一个有趣的线程.这不是直接相关的...但我只是想稍微深入了解一下,所以我对潜力有了更多了解.
我不确定这是否适用于 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)