NHibernate.Search + Lucene.NET 重复条目

发布于 2024-10-11 05:22:37 字数 1001 浏览 5 评论 0原文

当我从现有数据库构建初始索引时,Lucene 中的条目类型被索引为 <_hibernate_class:Castle.Proxies.MuestraProxy, DynamicProxyGenAssembly2>

但是,当使用 NHibernate 添加新实体时,它会被索引为 <_hibernate_class:RALVet.Model.Muestra, RALVet>} ,这会在 Lucene 中创建重复条目,一个作为真实类,另一个作为它的代理。

我在构建索引时尝试使用 NHibernateUtil.GetClass() 但它仍然返回代理。

这是构建初始索引的代码:

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();
    }

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();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

海的爱人是光 2024-10-18 05:22:37

编辑2:嗯,我对SO进行了另一次搜索,我认为你应该看看 这个答案。我无法重现您的问题,所以要么这里有其他东西在起作用(您的配置或域模型?),要么我完全没有抓住要点。祝你好运!


我将尝试猜测这里的原因(我不使用 C# 或 hql,所以如果它是这个领域的东西,我可能会运气不好)。我认为您所看到的是因为您使用了 .List() 方法的无类型版本。您应该尝试使用 .List() 来指定列出实体时所需的类型。

我认为

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

可以解决问题。


编辑:好的,显然它不适用于添加的 (显然代码片段吃了括号,所以如果这样做,请确保复制粘贴正确的版本)。

FWIW,我们在工作中所做的事情如下。我们使用 UnitOfWork 模式,因此 UnitOfWork 启动当前的 Nhibernate 配置和会话。我使用 Reflector 从 Vb.net 转到 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();
                }
            }
        }
    }
}

我将尝试以更精简的方式重现您的问题

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

乖乖 2024-10-18 05:22:37

好吧,我终于让它完美运行了。

问题是我使用拦截器在我的实体中注入 INotifyPropertyChanged 实现。删除拦截器使 NH.Search 和 Lucene.net 能够很好地工作。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文