使用Entity Framework和Oracle伪布尔值

4
我正在调查在我们组织中使用Entity Framework的可能性。我们使用Oracle DBMS,因此(好或坏)使用Oracle中常见的“伪布尔”模式,在这种模式下,没有布尔列(Oracle中不存在),而是有一个具有检查约束的1个字符列,将其强制为“Y”或“N”。
因此,如果我希望我的EF模型中的实体具有布尔属性,如何将其映射到数据库列,以使其为真时为“Y”,为假时为“N”? Entity Framework中是否有“转换器”或其他概念可以为我完成此操作?
还有一点很重要,我知道EF只能直接与SQL Server配合使用。我将使用DevArt dotConnect for Oracle来使用Oracle的EF。
http://www.devart.com/dotconnect/oracle/ 编辑: 其他ORM框架如NHibernate怎么样?它们是否可以“开箱即用”处理这种情况?
2个回答

3
Devart dotConnect for Oracle可以自动将NUMBER(1)列映射到System.Boolean,这简化了对这些列的操作 - 0表示false,非零(默认为1)表示true。不需要额外的操作。
如果您希望以char形式保留布尔值,则必须选择以下方法之一:
1. 将与字符列映射的属性保留为字符串类型。 在部分类实体中添加一个额外的包装器属性,其类型为布尔类型,并在getter和setter中相应地将字符串值转换为布尔值及其反向转换。
缺点: 这个包装器属性不能用于LINQ to Entities。
2. 创建一个视图,覆盖您的表,该视图将返回0或1而不是来自您的字符列的值。作为替代方案,在模型中创建一个DefiningQuery,用于此EntitySet(在这种情况下,不应将其添加到数据库中)。在大多数情况下,需要将属性的类型从“char(1)”更改为“bool”在SSDL中,从System.String更改为System.Boolean在CSDL中。您应编写一组存储过程来执行与实体相关的CUD操作,并将这些存储过程映射到可更新的此实体。
缺点: 工作量较大。

感谢您的回复。我考虑了这两个选项,但是希望找到一种方法,使NUMBER(1)和VARCHAR(1)得到相同的处理方式。对于我们来说,这些选项的缺点非常显著。而且我们无法改用NUMBER(1),因为我们有数百个使用VARCHAR(1)方法的表格。 - RationalGeek

1

目前,Oracle - DevArt和DataDirect都有自定义的Oracle连接提供程序层,您可以购买。此外,在CodeProject上还有准开源版本可用,实现了EDM for EF w / Oracle。我假设您正在使用其中之一。

不过,要回答您的问题,您需要修改ProviderManifest实现,以在调用GetEdmType()时返回适当的.NET类型。问题在于,此方法向您传递一个Oracle类型,并期望您返回EF理解的.NET类型(它理解所有基元类型,包括bool)。不幸的是,将CHAR(1)映射到布尔值并不理想,因为您原则上可能有其他CHAR(1)列不是布尔值。

解决这个问题的方法是创建一个Oracle用户定义类型(比如JKBOOL),将其映射到CHAR(1) - 然后您需要修改表以将CHAR(1)更改为JKBOOL。现在,您可以安全地将JKBOOL映射到System.Boolean中的GetEdmType()

很有趣的内容,但如果我要在Oracle中创建用户定义类型,并使用它来代替CHAR(1),我可能会直接使用NUMBER(1)来表示布尔类型,这是DevArt的EF提供程序已经正确映射的。 - RationalGeek
1
不同之处在于UDT仍然可以被任何SQL或PLSQL代码视为CHAR(1) - 因为UDT只是该类型的别名。将列更改为NUMBER将是一项破坏性的更改,并需要分析哪些查询、包和视图会受到影响。 - LBushkin
啊,现在我明白你的意思了。我一定会研究这个可能性。谢谢你提供的信息。 - RationalGeek
1
我在网上搜索了很久,但是很难找到任何关于如何正确覆盖/实现特定数据库类型的GetEdmType的工作示例。 我和使用Oracle时遇到的情况类似,因为我有很多声明为CHAR(1)的informix列,而它们实际上代表布尔值。 利用GetEdmType()似乎是正确的方法,只是我找不到示例。 - kdawg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接