Norm.MongoException: Connection timeout trying to

2019-08-29 06:38发布

I'm using Rob's mvc startesite http://mvcstarter.codeplex.com/ with ASP.Net MVC 2, Ninject2, NoRM (http://github.com/atheken/NoRM) and MongoDB. It works so fast and the developpement is even faster but I'm facing a big problem, I at some points, get connection timeout. I can't figure out what I'm doing wrong.

I already asked a question here : I get this error that I don't understand why, using NoRM and Mongo in my MVC project and here http://groups.google.com/group/norm-mongodb/browse_thread/thread/7882be16f030eb29 but I still in the dark.

Thanks a lot for the help!

EDITED* Here's my MongoSession object : public class MongoSession : ISession{

    private readonly Mongo _server;

    public MongoSession()
    {
        //this looks for a connection string in your Web.config - you can override this if you want
        _server = Mongo.Create("MongoDB");
    }

    public T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class {
        return _server.GetCollection<T>().AsQueryable().Where(expression).SingleOrDefault();
    }

    public IQueryable<T> All<T>() where T : class {
        return _server.GetCollection<T>().AsQueryable();
    }

    public void Save<T>(IEnumerable<T> items) where T : class {
        foreach (T item in items) {
            Save(item);
        }
    }

    public void Save<T>(T item) where T : class {
        var errors = DataAnnotationsValidationRunner.GetErrors(item);
        if (errors.Count() > 0)
        {
            throw new RulesException(errors);
        }
        _server.Database.GetCollection<T>().Save(item);
    }

    public void Delete<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class
    {
        var items = All<T>().Where(expression);
        foreach (T item in items)
        {
            Delete(item);
        }
    }

    public void Delete<T>(T item) where T : class
    {
        _server.GetCollection<T>().Delete(item);
    }

    public void Drop<T>() where T : class
    {
        _server.Database.DropCollection(typeof(T).Name);

    }

    public void Dispose() {
        _server.Dispose();
    }


}

And now my MongoRepositoryBase

public abstract class MongoRepositoryBase<T> : ISession<T> where T : MongoObject
{
    protected ISession _session;

    protected MongoRepositoryBase(ISession session)
    {
        _session = session;
    }

    public T Single(ObjectId id)
    {
        return _session.All<T>().Where(x => x.Id == id).FirstOrDefault();
    }

    public T Single(Expression<Func<T, bool>> expression)
    {
        return _session.Single(expression);
    }

    public IQueryable<T> All()
    {
        return _session.All<T>();
    }

    public void Save(IEnumerable<T> items)
    {
        foreach (T item in items)
        {
            Save(item);
        }
    }

    public void Save(T item)
    {
        _session.Save(item);
    }

    public void Delete(System.Linq.Expressions.Expression<Func<T, bool>> expression)
    {
        var items = _session.All<T>().Where(expression);
        foreach (T item in items)
        {
            Delete(item);
        }
    }

    public void DeleteAll()
    {
        var items = _session.All<T>();
        foreach (T item in items)
        {
            Delete(item);
        }
    }

    public void Delete(T item)
    {
        _session.Delete(item);
    }

    public void Drop()
    {
        _session.Drop<T>();
    }

    public void Dispose()
    {
        _session.Dispose();
    }
}

And an exemple of an other Repository implemantation :

public class PlaceRepository : MongoRepositoryBase<Place>, IPlaceRepository 
{
    public PlaceRepository(ISession session) : base(session)
    {
    }

    public List<Place> GetByCategory(PlaceCategory category, bool publishedOnly)
    {
        var query = _session.All<Place>()
            .OrderBy(x => x.Name)
            .Where(x => x.Category == category);

        if (publishedOnly) query = query.Where(x => x.Published);
        if (publishedOnly) query = query.Where(x => x.ShowOnMap);

        return query.ToList();
    }

    public Place FindByName(string name)
    {
        var query = _session.All<Place>()
            .Where(x => x.Name.ToLower().Contains(name.ToLower()))
            .Where(x => x.Published);

        return query.FirstOrDefault();
    }

    public string[] FindSuggestionsByName(string name)
    {
        var query = _session.All<Place>()
            .OrderBy(x => x.Name)
            .Where(x => x.Name.ToLower().StartsWith(name.ToLower()))
            .Where(x => x.Published);

        var places = query.ToList();

        var names = new string[places.Count];
        var i = 0;
        foreach (var place in places)
        {
            names[i++] = place.Name;
        }

        return names;
    }


}

2条回答
倾城 Initia
2楼-- · 2019-08-29 07:05

Vinny,

I've never used Ninject, so I could be way off with this suggestion. But it seems possible that having a static MongoSession instance might be holding connections open. Have you tried TransientBehavior instead of SingletonBehavior? Or maybe change your code to call Dispose (or use using) after you convert your ShortcutLinks to a List? All

var shortcutLionks = _session.All<ShortcutLinks>().ToList();
_session.Dispose();

A better approach might be to use some sort of repository or DAO where the session details are hidden from the controller. I have a RepositoryBase sample at http://www.codevoyeur.com/Articles/20/A-NoRM-MongoDB-Repository-Base-Class.aspx.

Stuart Harris has a similar, arguably more complete implementation at http://red-badger.com/Blog/post/A-simple-IRepository3cT3e-implementation-for-MongoDB-and-NoRM.aspx

Pooled MongoDB connections are relatively cheap to create, so it's probably best to make sure the data access methods are disposing after your done getting/saving data.

查看更多
\"骚年 ilove
3楼-- · 2019-08-29 07:14

If I add throw new NotImplementedException(); in the Dispose() method of my MongoRepositoryBase class it does not get call so I guess Ninject does not handle this for me, If I had

protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            _recipeRepo.Dispose();
            base.OnActionExecuted(filterContext);
        }

In my controller it does get call. It seems to be fine, thx!

查看更多
登录 后发表回答