如何加载PersistentList类型的属性包含数组参数中的一个或多个值的实体?

时间:2015-10-19 16:04:37

标签: codefluent

我的模型包含以下枚举和实体:

<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&lt;Language&gt;">
    <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模型中指定它?

2 个答案:

答案 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

enter image description here enter image description here

答案 1 :(得分:1)

当你正在处理我已经研究过但从未实现过的话题时,拿着我说的话。据说另一种方法是使用多值枚举(标志)

http://blog.codefluententities.com/2013/05/29/using-flags-enumeration-with-aspnet-mvc-and-codefluent-entities

使用此方法,您可以在实体和枚举之间创建关系,而不是将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 &gt; 0" />

正如我所说,采取我所说的一点点。我最终使用了一个实体而不是一个枚举,但仅仅因为那是我更熟悉的并且有一个截止日期。