我的模型包含以下枚举和实体:
<cf:enumeration name="Language" usePersistenceDefaultValue="false">
<cf:enumerationValue name="EN" value="1" default="true" />
<cf:enumerationValue name="NL" value="2" />
<cf:enumerationValue name="DE" value="3" />
</cf:enumeration>
<cf:entity name="Person" >
<cf:property name="Id" key="true" />
<cf:property name="Languages" typeName="CodeFluent.Runtime.Utilities.PersistentList<Language>">
<cf:message class="_doc">The languages that the person speaks</cf:message>
</cf:property>
<cf:method name="LoadPersonThatSpeaksOneOrMoreLanguages" checkLevel="None" memberAttributes="Public" >
<cf:body language="tsql" text="load(Language[] languages) from Person where Languages in (@languages)" />
</cf:method>
</cf:entity>
LoadPersonThatSpeaksOneOrMoreLanguages方法应该返回所有使用一种或多种语言的人。 生成的此方法的存储过程似乎不正确:
ALTER PROCEDURE [dbo].[Person_LoadPersonThatSpeaksOneOrMoreLanguages]
(
@languages [dbo].[cf_type_Person_LoadPersonThatSpeaksOneOrMoreLanguages_0] READONLY,
@_orderBy0 [nvarchar] (64) = NULL,
@_orderByDirection0 [bit] = 0
)
AS
SET NOCOUNT ON
DECLARE @_c_languages int; SELECT @_c_languages= COUNT(*) FROM @languages
SELECT DISTINCT [Person].[Person_Id], ...
FROM [Person]
WHERE [Person].[Person_Languages] IN (((SELECT * FROM @languages)))
问题1:
我怎样才能达到预期的效果?
我应该创建一个语言实体并指定人与语言之间的1:n关联吗?我不想拥有语言实体。
或者我可以指定必须将Languages属性转换为与table-valued-parameter(cf_type_Person_LoadPersonThatSpeaksOneOrMoreLanguages_0
)相同的类型吗?
问题2:
生成的PersonCollection
类包含方法LoadPersonThatSpeaksOneOrMoreLanguages
。此方法的参数是Language[]
类型。而不是数组我想要一个IEnumerable<Language>
。如何在我的XML模型中指定它?
答案 0 :(得分:2)
问题1
PersistentList
旨在存储一组简单值(int,string,enum,...),但不能直接在SQL中查询它们。实际上,PersistentList
被转换为数据库中的NVARCHAR
列,此列包含EN|NL
(管道分隔值)等值。数据库引擎不知道如何从字符串中提取单个值。也许你可以使用cf_SplitString
函数从列值创建一个表并用它做你想做的事情,但它似乎不是最简单的解决方案......
根据您的需要,您可以使用多值枚举:
<cf:enumeration name="Language" flags="true">
<cf:enumerationValue name="Unspecified" /> <!-- value=0 -->
<cf:enumerationValue name="EN" /> <!-- value=1 -->
<cf:enumerationValue name="NL" /> <!-- value=2 -->
<cf:enumerationValue name="FR" /> <!-- value=4 -->
</cf:enumeration>
您可以将它们与CFQL
:
-- Load Persons that speak the specified language
LOAD(Languages) WHERE (Languages & @Languages) = @Languages
-- Load Persons that speak at least one of the specified language
LOAD(Languages) WHERE (Languages & @Languages) <> 0
当然,最新的可能性是创建一个语言实体并使用表值参数。
http://blog.codefluententities.com/2014/07/16/persistent-list/ http://www.softfluent.com/documentation/Enumerations_Overview.html
问题2
来自CodeFluent实体的official blog:
答案 1 :(得分:1)
当你正在处理我已经研究过但从未实现过的话题时,拿着我说的话。据说另一种方法是使用多值枚举(标志)
使用此方法,您可以在实体和枚举之间创建关系,而不是将Languages属性设置为持久列表。
以下内容大多有效。使用Modeler创建实例时,我无法选择某些语言组合。不知道这是因为我在使用和设置标志枚举方面缺乏经验,还是因为建模者存在缺陷。但我确实设法创建了该方法,该部分似乎正在运行。
<cf:enumeration name="Language" multivalue="true" usePersistenceDefaultValue="false" namespace="Demo1" categoryPath="/Demo1">
<cf:enumerationValue name="Unspecified" default="true" />
<cf:enumerationValue name="EN" />
<cf:enumerationValue name="NL" />
<cf:enumerationValue name="DE" />
</cf:enumeration>
<cf:entity name="Person" namespace="Demo1">
<cf:property name="Id" key="true" />
<cf:property name="Languages" usePersistenceDefaultValue="false" typeName="{0}.Language" />
<cf:property name="FirstName" />
<cf:property name="LastName" />
<cf:instance>
<cf:instanceValue name="Id">d13447c6-a709-4c87-891d-e83674821915</cf:instanceValue>
<cf:instanceValue name="FirstName">Jon</cf:instanceValue>
<cf:instanceValue name="LastName">Smith</cf:instanceValue>
</cf:instance>
<cf:instance>
<cf:instanceValue name="Id">77e3730c-2cc3-457d-8bc0-d9a5e224b96a</cf:instanceValue>
<cf:instanceValue name="FirstName">Sam</cf:instanceValue>
<cf:instanceValue name="Languages">DE, SP</cf:instanceValue>
<cf:instanceValue name="LastName">Newman</cf:instanceValue>
</cf:instance>
<cf:method name="LoadPersonThatSpeaksOneOrMoreLanguages" body="LOAD() WHERE Languages > 0" />
正如我所说,采取我所说的一点点。我最终使用了一个实体而不是一个枚举,但仅仅因为那是我更熟悉的并且有一个截止日期。