Решение ошибки: элементы ORDER BY должны отображаться в списке выбора, если указан параметр SELECT DISTINCT - PullRequest
0 голосов
/ 07 февраля 2019

Причина ошибки: Я создаю метод для объекта TimeCard.Карта TimeCard относится к сущности Сотрудник.Метод сортирует TimeCards по имени сотрудника.

Очевидное решение Скопируйте хранимую процедуру из файла [имя_проекта] _procedures.sql и добавьте отсортированные столбцы в оператор выбора.Затем создайте необработанный метод, используя хранимую процедуру.

Вопрос: Есть ли лучшее решение.Мне не нравится очевидное решение, потому что оно сломается, если я добавлю дополнительные свойства к сущности TimeCard.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

SQL, сгенерированный CFE, недопустим, как объясняется в этом посте: Как связаны SQL DISTINCT и ORDER BY .Я думаю, что есть 2 обходных пути:

  1. Удалите DISTINCT из хранимой процедуры, если она не нужна:

    <cf:method name="LoadForActiveEmployeesSortedByEmployee" distinct="false" ... />
    
  2. Использованиенеобработанный метод с допустимым SQL-запросом:

    <cf:method body="LOAD() raw" rawBody="SELECT DISTINCT $TimeCard{Columns}$, EmployeeName FROM $TimeCard$ JOIN ... WHERE ... ORDER BY ...">
    
0 голосов
/ 07 февраля 2019

Я придумал исключительное решение, которым я делюсь.Если есть лучшее решение, пожалуйста, дайте мне знать.

Почему возникает эта ошибка: При использовании CFQL и добавлении предложения WHERE, в котором используются свойства связанной сущности, сгенерированная хранимая процедура добавляет DISTINCT коператор SELECT.Это приведет к ошибке, если вы также добавите порядок сортировки на основе свойства связанной сущности.

Шаг 1

Создание метода с использованием CFQL без порядка сортировкиenter image description here

Шаг 2

В BOM Producer установите для свойства NameSpaceImports значение System.Linq

enter image description here

Шаг 3

Создать метод Snipped, который использует LINQ для сортировки по свойству связанных сущностей

enter image description here

Caveat

При вызове метода возвращается тип List, а не TimeCardCollection

enter image description here

Ниже приведено полное определение xml.Чтобы воспроизвести исходную ошибку, установите для свойства LoadForActiveEmployeesSortedByEmployee значение true для enter image description here

<cf:project defaultNamespace="DemoSortByRelatedEntity" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" xmlns:cfx="http://www.softfluent.com/codefluent/modeler/2008/1" xmlns:cfps="http://www.softfluent.com/codefluent/producers.sqlserver/2005/1" xmlns:cfom="http://www.softfluent.com/codefluent/producers.model/2005/1" xmlns:cfasp="http://www.softfluent.com/codefluent/producers.aspnet/2011/1" defaultTargetFramework="4.0" defaultConnectionString="Database=DemoSortByRelatedEntity;Integrated Security=true" createDefaultMethodForms="true" createDefaultApplication="false" createDefaultHints="false">
  <cf:import path="Default.Surface.cfp" />
  <cf:producer name="SQL Server Producer" typeName="CodeFluent.Producers.SqlServer.SqlServerProducer, CodeFluent.Producers.SqlServer">
    <cf:configuration connectionString="Database=DemoSortByRelatedEntity;Integrated Security=true;Server=.\SQLExpress" produceViews="true" targetVersion="Sql2014" targetDirectory="..\DemoSortByRelatedEntity.Persistence" cfx:targetProjectLayout="UpdateItems, DontRemove" cfx:targetProject="..\DemoSortByRelatedEntity.Persistence\DemoSortByRelatedEntity.Persistence.dbproj" />
  </cf:producer>
  <cf:producer name="BOM Producer" typeName="CodeFluent.Producers.CodeDom.CodeDomProducer, CodeFluent.Producers.CodeDom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1bb6d7cccf1045ec">
    <cf:configuration compileWithVisualStudio="true" targetDirectory="..\DemoSortByRelatedEntity" cfx:targetProject="..\DemoSortByRelatedEntity\DemoSortByRelatedEntity.csproj" namespaceImports="System.Linq" cfx:targetProjectLayout="Update" />
  </cf:producer>
  <cf:producer name="ASP.NET WebForms Producer" typeName="CodeFluent.Producers.UI.AspNetProducer, CodeFluent.Producers.UI">
    <cf:configuration categoryPath="UI\AspNetWebForms" targetDirectory="..\DemoSortByRelatedEntity.Web" cfx:targetProject="..\DemoSortByRelatedEntity.Web\DemoSortByRelatedEntity.Web.csproj" />
  </cf:producer>
  <cf:entity name="TimeCard" namespace="DemoSortByRelatedEntity">
    <cf:property name="Id" key="true" />
    <cf:property name="InTime" typeName="datetime" />
    <cf:property name="OutTime" typeName="datetime" />
    <cf:property name="Employee" typeName="{0}.Employee" />
    <cf:method name="LoadForActiveEmployeesSortedByEmployee" body="LOAD() WHERE Employee.IsActive = TRUE ORDER BY Employee.Name" enabled="false" />
    <cf:method name="LoadForActiveEmployees" body="LOAD() WHERE Employee.IsActive = TRUE" />
    <cf:instance>
      <cf:instanceValue name="Id">58138358-1578-4f3a-9273-4fea17aa7dd5</cf:instanceValue>
      <cf:instanceValue name="InTime">1/1/2019 12:00:00 AM</cf:instanceValue>
      <cf:instanceValue name="OutTime">2/2/2019 12:00:00 AM</cf:instanceValue>
      <cf:instanceValue name="Employee">a57ba60a-5e6a-4df0-88b9-283d60517b66</cf:instanceValue>
    </cf:instance>
    <cf:instance>
      <cf:instanceValue name="Id">487a8bcf-89a1-49d6-b970-ae8d32c0f7f2</cf:instanceValue>
      <cf:instanceValue name="InTime">2/3/2019 12:00:00 AM</cf:instanceValue>
      <cf:instanceValue name="OutTime">2/4/2019 12:00:00 AM</cf:instanceValue>
      <cf:instanceValue name="Employee">4762eeea-dcc7-4d7e-8b07-1f78b73657ed</cf:instanceValue>
    </cf:instance>
    <cf:instance>
      <cf:instanceValue name="Id">5f039986-e423-460f-aa7e-9b28e2a507b3</cf:instanceValue>
      <cf:instanceValue name="InTime">2/5/2019 12:00:00 AM</cf:instanceValue>
      <cf:instanceValue name="OutTime">2/6/2019 12:00:00 AM</cf:instanceValue>
      <cf:instanceValue name="Employee">c7ae6667-55d4-4ba2-8576-4c0c950b7231</cf:instanceValue>
    </cf:instance>
    <cf:setSnippet name="LoadForActiveEmployeesSortedByEmployeeFix1" language="CSharp"><![CDATA[
    public static System.Collections.Generic.List<TimeCard> LoadForActiveEmployeesSortedByEmployeeFix1()
        {
            return LoadForActiveEmployees().OrderBy(x => x.Employee.Name).ToList();
        }
]]></cf:setSnippet>
  </cf:entity>
  <cf:entity name="Employee" namespace="DemoSortByRelatedEntity">
    <cf:property name="Id" key="true" />
    <cf:property name="Name" entityDisplay="true" />
    <cf:property name="IsActive" typeName="bool" />
    <cf:instance>
      <cf:instanceValue name="Id">a57ba60a-5e6a-4df0-88b9-283d60517b66</cf:instanceValue>
      <cf:instanceValue name="IsActive">True</cf:instanceValue>
      <cf:instanceValue name="Name">Jon</cf:instanceValue>
    </cf:instance>
    <cf:instance>
      <cf:instanceValue name="Id">4762eeea-dcc7-4d7e-8b07-1f78b73657ed</cf:instanceValue>
      <cf:instanceValue name="Name">Mike</cf:instanceValue>
    </cf:instance>
    <cf:instance>
      <cf:instanceValue name="Id">c7ae6667-55d4-4ba2-8576-4c0c950b7231</cf:instanceValue>
      <cf:instanceValue name="IsActive">True</cf:instanceValue>
      <cf:instanceValue name="Name">Lisa</cf:instanceValue>
    </cf:instance>
  </cf:entity>
</cf:project>
...