XPO是我公司选择的对象关系映射器。有关利弊的任何想法吗?
我只是在寻找关于该产品的一般感觉和轶事。我们没有转向XPO。我们正在摆脱存在于应用程序中的硬编码sql字符串,并完全移动到ORM以进行所有数据访问。
答案 0 :(得分:16)
其他人可能会提出技术答案(例如查询语法,使用缓存,轻松或以其他方式映射到现有数据库结构) - 但如果你有一个已建立的ORM层,答案可能是
“为什么要改变?”
我已经成功使用XPO多年来已经建立了一个拥有数百名用户的商业产品。我发现它快速,灵活并且能够胜任。我认为目前没有必要改变,因为我们的数据量并不是特别大,而且主要是缓存(主要是缓存)是我们可以解决的问题。
如果我重新开始,我肯定会看看NHibernate和ADO.NET实体框架。但在实践中,一切都很好;在技术问题出现之前,我很可能会考虑项目的商业情况。
例如,NHibernate是开源的 - 是否有一个可行的社区来支持该工具并提供(如有必要)商业支持?
XPO来自工具供应商,他们是否可能在产品的整个生命周期内保持业务?
ADO.NET实体框架来自微软,他因更频繁地更换数据库技术而臭名昭着拉里用喷气燃料填充他的战斗机 - 这也会逐渐消失吗?
答案 1 :(得分:9)
我发现XPO非常令人沮丧。 ORM的主要思想是抽象出底层数据结构。但很快你就会注意到它们的默认字符串长度被硬编码为60个字符,因此你最终会在每个字符串周围添加这些丑陋的string.unlimited事物。非常抽象......
当建模更复杂的对象时,你必须使用很多在对象模型中没有位置的语法,比如XPCollection。我想在类上存储一个包含字典字典的类,但遗憾的是XPO无法将其自动存储到数据库中。
因此,虽然它适用于简单类型,但是当您想要存储更复杂的东西时,它会很快崩溃。这与他们平庸的支持相结合确实留下了很多不足之处。
答案 2 :(得分:4)
整体上XPO很容易使用。但是,当您计划使用旧数据库或尝试将其引入棕色地带应用程序时,可能会有点痛苦。我遇到的最痛苦的障碍是:
正如丹尼斯在评论中指出的那样,自从我最初写这篇答案以来,XPO得到了极大的改善。特别是,下面的事情不再是问题:
此外,下面的问题将不再是今年晚些时候发布的XPO版本的问题:
总而言之,XPO得到了极大的改进。大多数痛苦的障碍都被删除了。在处理旧数据库时,您仍然可能遇到问题。但总的来说XPO变得非常方便使用。
答案 3 :(得分:4)
我现在已经使用它6-7个月了,卖家对我而言,他们所有的UI组件都与XPO相对无缝地工作 - 而且他们的UI组件是顶级的。
有些人可能会注意到他们的论坛监控不力,流量很少 - 这是事实。秘诀就是填写门票。他们迅速,准确地回复所有支持票。
答案 4 :(得分:2)
XPO ver 10.2现在支持StoredProcedures和SqlQueries。请参阅信息 here ...
答案 5 :(得分:0)
利弊比较什么?那里有很多替代方案,最受欢迎的是nHibernate,其中包含了新的“ADO.NET实体框架”。
无论如何,根据您的情况和要求,有数百个答案。
答案 6 :(得分:0)
我喜欢你可以创建类的事实,xpo为你创建表和关系 - 所以你可以从一个空白的数据库开始。
我不喜欢的一个问题是,当我想要删除大量内容时,它会通过我的收藏并对每个收集进行删除。这需要很长时间,所以对于这种情况,我不得不写一些自定义的sql(从表中删除等等)。我不是XPO的专家,但这就是我找到的。
答案 7 :(得分:0)
我的第二个事实是删除带有一些集合的复杂对象真的很长。到目前为止,文档或论坛无法帮助我解决这个问题。
除此之外,使用起来非常简单,让您快速前进。
很难弄清楚你的内存使用情况,我的设计中有复杂的大对象,使用它们的内存比我想象的要大。
答案 8 :(得分:0)
这就是开始编写域对象所需要做的一切(尝试在其他系统中执行相同的操作):
using System;
using DevExpress.Xpo;
using DevExpress.Data.Filtering;
using NUnit.Framework;
namespace XpoTdd {
public class Person:XPObject {
public Person(Session session) : base(session) { }
public string FirstName { get; set; }
public string LastName { get; set; }
[Persistent]
public string FullName { get { return FirstName + " " + LastName; } }
}
[TestFixture]
public class PersonTests {
[Test]
public void TestPersistence() {
const string connStr = "Integrated Security=SSPI;Pooling=false;Data Source=(local);Initial Catalog=XpoTddTest";
UnitOfWork session1 = new UnitOfWork();
session1.ConnectionString = connStr;
Person me = new Person(session1);
me.FirstName = "Roman";
me.LastName = "Eremin";
session1.CommitChanges();
UnitOfWork session2 = new UnitOfWork();
session2.ConnectionString = connStr;
me = session2.FindObject<Person>(CriteriaOperator.Parse("FullName = 'Roman Eremin'"));
Assert.AreEqual("Roman Eremin", me.FullName);
}
}
}