我已经为我写过的存储库编写了一些测试。
public interface IEntity<T> {
T Id { get; set; }
}
public abstract class Entity<TEntity> : IEntity<TEntity> {
[BsonId]
public TEntity Id { get; set; }
public override string ToString() {
return JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings {
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
});
}
}
public interface IMongoRepository<TEntity, TE> : IQueryable<TEntity> where TEntity : IEntity<TE> {
string ConnectionString { get; set; }
bool Remove<T>(TEntity entity);
bool Save<T>(TEntity entity);
bool Update<T>(TEntity entity);
}
public sealed class MongoRepository<TEntity, TU> : IMongoRepository<TEntity, TU>
where TEntity : Entity<TU> {
public MongoCollection<TEntity> Collection {
get {
var client = new MongoClient(ConnectionString);
var server = client.GetServer();
var db = server.GetDatabase("mykantina");
return db.GetCollection<TEntity>(typeof (TEntity).Name.Pluralize());
}
}
private IQueryable<TEntity> Queryable {
get { return Collection.FindAll().AsQueryable(); }
}
#region IRepository<T,U> Implementation
public string ConnectionString { get; set; }
public bool Remove<T>(TEntity entity) {
try {
var e = entity as Entity<TU>;
if (e == null) return false;
WriteConcernResult resultConcern = Collection.Remove(Query.EQ("_id", e.Id.ToBson()));
return true;
}
catch (Exception e) {
return false;
}
}
public bool Save<T>(TEntity entity) {
try {
WriteConcernResult resultConcern = Collection.Save(entity);
return true;
}
catch (Exception e) {
return false;
}
}
public bool Update<T>(TEntity entity) {
throw new NotImplementedException();
}
#endregion
#region IQueryable<T> Implementation
public IEnumerator<TEntity> GetEnumerator() {
return Queryable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return Queryable.GetEnumerator();
}
public Type ElementType {
get { return Queryable.ElementType; }
}
public Expression Expression {
get { return Queryable.Expression; }
}
public IQueryProvider Provider {
get { return Queryable.Provider; }
}
#endregion
}
以下是测试:
[Test]
public void LinearInsertsToMongoDb() {
Stopwatch total = Stopwatch.StartNew();
for (int i = 0; i <= 100000; i++) {
Stopwatch sw = Stopwatch.StartNew();
var isOk = _repository.Save<Widget>(new Widget {
Name = "Calendar" + i
});
sw.Stop();
Trace.WriteLine(string.Format("Took to insert {0}ms - item {1}", sw.ElapsedMilliseconds, i));
}
Trace.WriteLine(string.Format("================================================================"));
total.Stop();
Trace.WriteLine(string.Format("Total = {0}ms", total.ElapsedMilliseconds));
}
Time result: Total = 212398ms
private static object _sync = new object();
[Test]
public void ConcurrentInsertsToMongoDb() {
Stopwatch total = Stopwatch.StartNew();
var waitHandlers = new List<WaitHandle>();
for (int i = 0; i < 50; i++) {
var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset);
waitHandlers.Add(threadFinish);
var thread = new Thread(() => {
RunMongoThread();
threadFinish.Set();
});
thread.Start();
}
WaitHandle.WaitAll(waitHandles: waitHandlers.ToArray());
Trace.WriteLine(string.Format("================================================================"));
total.Stop();
Trace.WriteLine(string.Format("Total = {0}ms", total.ElapsedMilliseconds));
}
private static void RunMongoThread() {
for (var i = 0; i < 300; i++) {
bool isLocked = false;
try {
Monitor.Enter(_sync, ref isLocked);
var widget = new Widget {
Name = "Calendar" + i
};
var isOk = _repository.Save<Widget>(widget);
Trace.WriteLine(string.Format("Object: {0} - Thread {1}", widget, Thread.CurrentThread.ManagedThreadId));
}
finally {
if(isLocked)
Monitor.Exit(_sync);
}
}
}
Time result: Total 31303ms
问题是我做错了什么以及为什么这么慢?