2013-10-01 6 views
2

Предположим, у меня была база данных с таблицей научных статей, и была колонка, в которой указывалось, была ли статья опубликована в «крупном» журнале (как немного). Возможно, мне захочется запустить запрос, чтобы перечислить каждого автора и были ли они опубликованы в одном из них. Он может выглядеть так:NHibernate: no persister for CastProjection

select author, max(cast(major_journal as INT)) as ever_published 
from AcademicPapers 
group by author; 

Прохладный! теперь я хочу сделать это с NHibernate. Режущий остальная часть запроса, и фокусировка на max(cast(...)) частей, я попытался это:

Projections.Max<AcademicPaper>( 
    m => Projections.Cast(NHibernateUtil.Int32, Projections.Property("major_journal"))) 
    .WithAlias(() => report.EverPublished) 

Однако, когда я запускаю это, я получаю исключение, которое более или менее мне непонятно:

No persister for: NHibernate.Criterion.CastProjection 

Я знаю со 100% уверенностью, что я неправильно структурировал этот проект, но мне еще не удалось найти хорошую ссылку для NHibernate; каждый раз, когда я его ищу, я просто нахожу StackOverflow. Я хотел бы получить либо руку с этой конкретной проблемой, либо ссылку на достойную запись того, что на самом деле происходит здесь.

Благодарим вас!

+1

Я нашел решение своей непосредственной проблемы. 'Projections.Max' перегружен несколько раз, одна перегрузка может просто взять другую проекцию, в данном случае' Projections.Cast'. Таким образом, линия нужно быть таким: 'Projections.Max ( Projections.Cast (NHibernateUtil.Int32, Projections.Property ("major_journal")) .WithAlias ​​(() => report.EverPublished)' Мой оригинал попытка заключалась в использовании излишне сложной версии «Projections.Max». – phil

ответ

0

Надеюсь, я правильно понял вашу проблему, поэтому вы просто хотите, чтобы все авторы, у которых есть хотя бы одна бумага, у которой этот флаг установлен на true, правильно?

Почему вы не просто используете Linq, его способ проще писать и должен работать для таких простых сценариев. Я хотел бы также сопоставить свой флаг на BOOL, так что я думаю, что нет необходимости делать Max операцию на все ... Примера:

var authorsWithPublications = session.Query<Paper>() 
    .Select(p => new { Author = p.Author, HasPublished = p.HasPublished }) 
    .Where(p => p.HasPublished == true).ToList(); 

Я использовал этот простой сценарий, дайте мне знать, если это Безразлично «т соответствует ваш вопрос:

Entity + Mapping:

public class Paper 
{ 
    public virtual int Id { get; set; } 
    public virtual string Author { get; set; } 
    public virtual bool HasPublished { get; set; } 
    public virtual string Description { get; set; } 
    public virtual string Something { get; set; } 
    public virtual string SomethingElse { get; set; } 
} 

public class PaperMap : ClassMap<Paper> 
{ 
    public PaperMap() 
    { 
     Id<int>("Id"); 

     Map(p => p.Author); 
     Map(p => p.HasPublished); 
     Map(p => p.Description); 
     Map(p => p.Something); 
     Map(p => p.SomethingElse); 
    } 
} 

Создание некоторых тестовых данных и запрос

using (var session = sessionFactory.OpenSession()) 
{ 
    Random r1 = new Random(); 

    for (int i = 0; i < 100; i++) 
    { 
     session.Save(new Paper() 
     { 
      Author = "Author" + i, 
      HasPublished = r1.Next(0, 2) == 0 ? false : true, 
      Description = "Description" +i, 
      Something = "Something" + i, 
      SomethingElse = "something else" + i 
     }); 
    } 
    session.Flush(); 

    var authorsWithPublications = session.Query<Paper>() 
       .Select(p => new { Author = p.Author, HasPublished = p.HasPublished }) 
       .Where(p => p.HasPublished == true).ToList(); 
} 

Это на самом деле возвращает меня именно эти авторы ... Вы могли бы обработать это еще иметь только отличный результат ...

: редактировать начинается: для запроса всех авторов с максимальным значением флага , то становится немного сложнее с LINQ, следующий запрос LINQ вернет этот результат:

var authorsWithPublications = session.Query<Paper>() 
       .GroupBy(p => new { Author = p.Author }) 
       .Select(p => new { 
        Author = p.Key, 
        HasPublished = p.Max(c=> c.HasPublished) 
       }) 
       .ToList(); 

Но если c.HasPublished битового поля в SqlServer, это даст вам исключение SQL, что макс не разрешено в полях бит.

Попытка преобразовать логическое значение в целое wihtin заявление Linq как

...HasPublished = p.Max(c => c.HasPublished == true ? 1 : 0) 

сгенерирует исключение Code supposed to be unreachable, потому что он не поддерживается NHibernate ...

Единственный способ, которым я нашел, чтобы получить первый Linq ход запроса является заданием формулы в отображении:

Map(p => p.HasPublished).Formula("cast (HasPublished as int)"); 

Теперь эта формула будет применяться для всех операторов выбора, оператор будет выглядеть следующим образом:

select paper0_.Author as col_0_0_, max(cast (paper0_.HasPublished as int)) as col_1_0_ 
from [Paper] paper0_ 
group by paper0_.Author 

в любом случае вы уже нашли решение и следующий делает фактически то же самое, без необходимости формулы

var criteria = session.CreateCriteria<Paper>(); 
criteria.SetProjection(
    Projections.Group<Paper>(p=>p.Author), 
    Projections.Max(
     Projections.Cast(NHibernateUtil.Int32, Projections.Property("HasPublished"))) 
    ); 
var result = criteria.List(); 

Но, может быть, мы оба чему-то научились;)

+0

Что я ищу, немного отличается, хотя я бы не сомневался, что подход linq, вероятно, сработает для него, я хочу вернуть все (отдельные) авторы, а затем 0 или 1, который указывает, публикуются ли они. Меня не просили отделить опубликованных и не опубликованных авторов от двух отдельных запросов. Спасибо за ваш ответ, я буду рад принять его как пока он все еще фиксирует это первоначальное намерение. Я также добавил комментарий к исходному вопросу с помощью решения, которое я нашел. (I ca не отправляйте ответ, потому что я здесь совершенно новый.) – phil

+0

Я очень ценю такой подробный пример ответа, еще раз спасибо. – phil

+0

@phil Я добавил еще несколько выводов к моему ответу, возможно, также интересно для вас – MichaC

Смежные вопросы