开发者

NHibernate.Search + Lucene.NET duplicate entries

When I build the initial index from an existing database, the type of the entries in Lucene get indexed as <_hibernate_class:Castle.Proxies.MuestraProxy, DynamicProxyGenAssembly2>

However, when a new entity is added using NHibernate it gets indexed as <_hibernate_class:RALVet.Model.Muestra, RALVet>} which creates duplicate entries in Lucene, one as the real class and another one as its proxy.

I've tried using NHibernateUtil.GetClass() when building the index but it still returns the proxy.

This is the code that builds the initial index:

private static void CreateIndex<T>()
    {
        var fullTextSession =
            NHibernate.Search.Search.CreateFullTextSession(BootStrapper.SessionFactory.OpenSession());
        using(var tran = fullTextSession.BeginTransaction())
        {
            var query = fullTextSession.CreateQuery(string.Concat("from ", typeof (T).Name));

            foreach (var doc in query.List())
            {
                fullTextSession.Index(doc);
     开发者_开发百科       //  fullTextSession.Index(NHibernateUtil.GetClass(doc));
            }
            tran.Commit();
        }
        fullTextSession.Close();
    }


Edit 2: Well, i did another search on SO and i think that you should take a look on this answer. I can't reproduce your problem, so either there's something else at play here (your config or domain models?) or i'm completely missing the point. Good luck!


I'm going to try and guess at the reason here (i don't use C# or the hql, so if it's something in this area, i may be out of luck). I think what you see is because you use the typeless version of the .List() method. You should try and use .List<T>() that will specify the type you expect when listing your entities.

I think that

foreach (var doc in query.List<T>()) { fullTextSession.Index(doc); }

should do the trick.


Edit: ok so apparently it's not working with the added <T> (apparently the code snippet ate the brackets, so make sure you copy-pasted the right version if you did so).

FWIW, what we're doing at work is below. We use the UnitOfWork pattern so the UnitOfWork embarks the current Nhibernate configuration and session. I used Reflector to go from Vb.net to c#

            DocumentBuilder db = SearchFactoryImpl.GetSearchFactory(UnitOfWork.Configuration).GetDocumentBuilder(typeof(T));
            IList<T> results = null;
            PropertyInfo pi = typeof(T).GetProperty("Id");
            // an internal method that pages the data from the DB, returning true while there's more to process
            while (this.InnerPageThrough<T>(ref results, pageNumber, itemsPerPage))
            {
                IndexWriter iw = new IndexWriter(this.CheminIndexation + @"\" + typeof(T).Name, new StandardAnalyzer(), false);
                iw.SetMaxMergeDocs(0x186a0);
                iw.SetMergeFactor(0x3e8);
                iw.SetMaxBufferedDocs(0x2710);
                iw.SetUseCompoundFile(false);
                using (Timer.Start("indexing + Conversions.ToString(results.Count) + " objects " + typeof(T).Name))
                {
                    // Sorry, looks like crap through the translation
                    IEnumerator<T> VB$t_ref$L3;
                    try
                    {
                        VB$t_ref$L3 = results.GetEnumerator();
                        while (VB$t_ref$L3.MoveNext())
                        {
                            T Entity = VB$t_ref$L3.Current;
                            object EntityId = RuntimeHelpers.GetObjectValue(pi.GetValue(Entity, null));
                            iw.AddDocument(db.GetDocument(Entity, RuntimeHelpers.GetObjectValue(EntityId), typeof(T)));
                        }
                    }
                    finally
                    {
                        if (VB$t_ref$L3 != null)
                        {
                            VB$t_ref$L3.Dispose();
                        }
                    }
                }
                iw.Flush(true, true, true);
                iw.Close();
                UnitOfWork.CurrentSession.Clear();
                pageNumber++;
            }
            if (Optimize)
            {
                using (Timer.Start("optimising index"))
                {
                    IndexWriter iw = new IndexWriter(this.CheminIndexation + @"\" + typeof(T).Name, new StandardAnalyzer(), false);
                    iw.Optimize();
                    iw.Close();
                }
            }
        }
    }
}

I'm going to try and reproduce you problem in a leaner way


Ok, I finally got it working perfectly.

The problem was that I was using an interceptor to inject the INotifyPropertyChanged implementation in my entities. Removing the interceptor made NH.Search and Lucene.net to work nicely.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜