c# – 是否可以在不获取所有链接的情况下获取链接表?
好吧,首先我想说我正在为我的项目使用NHibernate,在这个项目中我们有(除其他外)一个同步功能(从中央MSSQL数据库同步到本地SQLite).现在我知道NHibernate并不是为了同步数据库,但我还想这样做.
我有一个中型大型数据库模型,所以我不能在这里添加它,但问题是我有两个数据表,一个链接表将它们都链接起来. 数据库模型: | Product | | ProductLinkProducer | | Producer | |--------------------| |---------------------| |---------------------| | Id | | LinkId | | Id | | Name | | Product | | Name | | ProductLinkProducer| | Producer | | ProductLinkProducer | 数据库: | Product | | ProductLinkProducer | | Producer | |---------| |---------------------| |----------| | Id | | LinkId | | Id | | Name | | ProductId | | Name | | | | ProducerId | | | 因此,在同步期间,我首先从Product表中复制所有数据,然后从Producer表复制(基本上是var products = session.Query< Products>().ToList()).这是由NHibernate在一个语句中完成的: select product0_.id as id2_,product0_.name as name2_ from Product product0_ 现在我必须从第一个会话中逐出所有项目(products.ForEach(x => session.Evict(x));) 然后save(products.ForEach(x => syncSession.save(x));)是每行一个插入(如预期的那样). 因此,当在链接表中保存数据时,我希望也只有一个选择.然而事实并非如此.因为首先它选择……如上所述.但现在在每行插入之前,它会为产品和生产者做更多的选择. 所以它看起来像: 产品介绍: >选择 制片人: >选择 ProdLinkProducer: >选择 那么有没有避免这种行为? 编辑 为了更好地解释我所做的事情,我创建了一个小型测试项目.它可以在这里找到:https://github.com/tb2johm/NHibernateSync EDIT2 我找到了一种让它起作用的方法,但我不喜欢它. 解决方法
我无法找到NHibernate开箱即用的方式来做你想问的事.
然而,通过手动将FK引用(代理类)重新绑定到新会话,我能够获得所需的行为(我猜想有什么比没有好的东西:): var links = session.Query<ProductLinkProducer>().ToList(); links.ForEach(x => session.Evict(x)); foreach (var link in links) { link.Product = syncSession.Get<Product>(link.Product.Id); link.Producer = syncSession.Get<Producer>(link.Producer.Id); syncSession.Save(link); } syncSession.Flush(); 这是使用NHibernate元数据服务的通用版本: static IEnumerable<Action<ISession,T>> GetRefBindActions<T>(ISessionFactory sessionFactory) { var classMeta = sessionFactory.GetClassMetadata(typeof(T)); var propertyNames = classMeta.PropertyNames; var propertyTypes = classMeta.PropertyTypes; for (int i = 0; i < propertyTypes.Length; i++) { var propertyType = propertyTypes[i]; if (propertyType.IsAssociationType && !propertyType.IsCollectionType) { var propertyName = propertyNames[i]; var propertyClass = propertyType.ReturnedClass; var propertyClassMeta = sessionFactory.GetClassMetadata(propertyClass); yield return (session,target) => { var oldValue = classMeta.GetPropertyValue(target,propertyName,EntityMode.Poco); var id = propertyClassMeta.GetIdentifier(oldValue,EntityMode.Poco); var newValue = session.Get(propertyClass,id); classMeta.SetPropertyValue(target,newValue,EntityMode.Poco); }; } } } 并将其应用于您的Sync方法: private static void Sync<T>(string tableName,ISession session,ISession syncSession) { Console.WriteLine("Fetching data for ####{0}####...",tableName); var sqlLinks = session.Query<T>(); var links = sqlLinks.ToList(); Console.WriteLine("...Done"); Console.WriteLine("Evicting data..."); links.ForEach(x => session.Evict(x)); Console.WriteLine("...Done"); Console.WriteLine("Saving data..."); var bindRefs = GetRefBindActions<T>(syncSession.SessionFactory).ToList(); foreach (var link in links) { foreach (var action in bindRefs) action(syncSession,link); syncSession.Save(link); } Console.WriteLine("...Flushing data..."); syncSession.Flush(); Console.WriteLine("...Done"); Console.WriteLine("nnn"); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |