XPO是我公司首选的对象关系映射器。关于利弊的任何想法?
我只是在寻找有关该产品的一般感觉和轶事。我们不会切换到 XPO。我们只是摆脱了应用程序中的硬编码 sql 字符串,并完全转移到 ORM 以进行所有数据访问。
其他人可能会提供技术答案(例如查询语法、缓存的使用、映射到现有数据库结构的简便性或其他方式)——但如果你有一个已建立的 ORM 层,答案可能是
“为什么要改变”?
多年来,我在一个拥有数百名用户的成熟商业产品中成功使用了 XPO。我发现它快速、灵活并且可以胜任。目前我认为没有任何改变的必要,因为我们的数据量并不是特别大,而且我们可以解决的问题(主要是缓存)。
如果我重新开始,我肯定会同时查看 NHibernate 和 ADO.NET Entity Framework。但实际上,一切都很好。我很可能会在技术问题之前查看该项目的商业情况。
例如,NHibernate 是开源的——那里是否有一个可行的社区来支持该工具并提供(如有必要)商业支持?
XPO 来自工具供应商,他们是否可能在产品的整个生命周期内继续营业?
ADO.NET Entity Framework 来自微软,它以更频繁地更改数据库技术而臭名昭著,然后拉里给他的战斗机加满了喷气燃料——这也会消失吗?
我发现 XPO 非常令人沮丧。ORM 的主要思想是抽象出底层数据结构。但是很快你会注意到它们的默认字符串长度硬编码为 60 个字符,所以你最终会在每个字符串周围添加这些丑陋的 string.unlimited 东西。这么多的抽象...
在对更复杂的对象建模时,您必须使用很多在对象模型中确实没有位置的语法,例如 XPCollection。我想存储一个类,该类在类上有一个字符串字典,但遗憾的是 XPO 无法自动将其存储到数据库中。
因此,虽然它适用于简单类型,但当您想要存储更复杂的东西时,它很快就会崩溃。再加上他们平庸的支持,确实有很多不足之处。
我已经使用它 6 到 7 个月了,对我来说,卖家的事实是他们所有的 UI 组件都可以与 XPO 相对无缝地工作——而且他们的 UI 组件是一流的。
有些人可能会注意到他们的论坛受到的监控很差,而且几乎没有有用的流量——这是真的。秘诀就是填票。他们对所有支持请求做出快速、准确的响应。
总体而言,XPO 易于使用。但是,当您计划使用遗留数据库或尝试将其引入棕地应用程序时,可能会有些痛苦。我遇到的最痛苦的障碍是:
正如丹尼斯在评论中指出的那样,自从我最初写了这个答案以来,XPO 有了很大的改进。特别是,以下事情不再是问题:
此外,在今年晚些时候发布的下一个 XPO 版本中,以下问题将不再是问题:
总而言之,XPO 得到了很大的改进。大多数痛苦的障碍都被移除了。在使用遗留数据库时,您仍然会遇到问题。但总的来说,XPO 使用起来相当方便。
XPO 10.2 版现在支持 StoredProcedures 和 SqlQueries。在这里查看信息 ...
相比的优缺点是什么?那里有很多替代品,最受欢迎的是 nHibernate,新的孩子“ADO.NET Entity Framework”就在其中。
无论如何,根据您的情况和要求,有数百个答案。
我喜欢这样一个事实,即您可以只创建类,而 xpo 会为您创建表和关系——因此您可以从一个空白数据库开始。
我不喜欢的一个问题是,当我想删除一大堆东西时,它会通过我的收藏并删除每一个。这需要很长时间,所以对于这种情况,我不得不编写一些自定义 sql(从表中删除等等)。我不是 XPO 方面的专家,但这就是我发现的。
我第二个事实是删除带有一些集合的复杂对象需要非常非常长的时间。到目前为止,文档或论坛无法帮助我解决这个问题。
除此之外,它使用起来非常简单,让您快速上手。
也很难弄清楚你的内存使用情况,我的设计中有复杂的大对象,使用它们比我想象的要大得多。
这是您开始编写域对象所需要做的一切(尝试在其他系统中执行相同操作):
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);
}
}
}