Зачем мне устанавливать псевдоним для моей проекции, если это необязательно? - PullRequest
4 голосов
/ 09 августа 2010

Я читаю документацию о DetachedCriteria.Документация ясно показывает, что установка псевдонима для вашей проекции является необязательной.Однако всякий раз, когда я опускаю псевдоним, мои свойства модели не содержат данных.Вот мои две тестовые модели.

[ActiveRecord("INCIDENT")]
public class Incident : ActiveRecordBase<Incident>
{
    [PrimaryKey(PrimaryKeyType.Native, "INCIDENT_ID", ColumnType = "Int32")]
    public virtual int IncidentId { get; set; }

    [Property("CREATION_DATETIME", ColumnType = "DateTime")]
    public virtual DateTime? CreationDatetime { get; set; }

    [BelongsTo("CAUSE_CD")]
    public virtual Cause Cause { get; set; }
}

[ActiveRecord("CAUSE")]
public class Cause : ActiveRecordBase<Cause>
{
    [PrimaryKey(PrimaryKeyType.Native, "CAUSE_CD", ColumnType = "String")]
    public virtual string CauseCd { get; set; }

    [Property("CAUSE_DESC", ColumnType = "String", NotNull = true)]
    public virtual string CauseDesc { get; set; }
}

Вот то, что я использую для запроса к базе данных.

DetachedCriteria incidentCriteria = DetachedCriteria.For<Incident>("i")
.SetProjection(Projections.ProjectionList()
   .Add(Projections.Property("i.IncidentId"))
   .Add(Projections.Property("i.CreationDatetime"))
)
.SetResultTransformer(Transformers.AliasToBean<Incident>());
IList<Incident> incidents = Incident.FindAll(incidentCriteria);

Оба свойства проекций не заполняются, если я не установил псевдоним.Итак, мой вопрос: почему псевдоним необязателен?Я уверен, что просто упускаю что-то еще.Но если я добавлю случайный псевдоним (например, abc), он вернет ошибку, говорящую о том, что он не может найти свойство "abc" в классе Incident.Справедливо, я добавляю соответствующий псевдоним, чтобы соответствовать моим именам свойств.И вуаля!Мои свойства теперь заполняются.

Теперь возникает вопрос, когда я хочу запросить таблицу поиска.Я добавляю

.Add(Projections.Property("c.CauseDesc"), "CauseDesc")

в свой ProjectionList и добавляю

.CreateCriteria("i.Cause", "c")

Но теперь он жалуется, что не может найти "CauseDesc" из моей модели инцидентов.

Чтомне не хватает этого критерия?

Обновление: следующий код

IList<Incident> results = sess.CreateCriteria<Incident>("i")
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.Property("i.IncidentId"), "IncidentId")
        .Add(Projections.Property("i.CreationDatetime"), "CreationDatetime")
        .Add(Projections.Property("c.CauseDesc"), "CauseDesc")
    )
    .Add(Expression.Gt("i.IncidentId", 1234567))
    .CreateAlias("Cause", "c")
    .List<Incident>();

Это создает действительный запрос (я проверил его с помощью профилировщика), но, похоже, возникают проблемызаполнение моего общего списка.Это дает мне ошибку "Значение \" System.Object [] \ "не относится к типу \" oms_dal.Models.Incident \ "и не может использоваться в этой универсальной коллекции. \ R \ nПараметр name: value".Тем не менее, все работает нормально, если я не использую проекцию, а затем выбирает более 50 полей, которые мне не нужны.Означает ли это, что я вынужден использовать DTO в этих обстоятельствах?

1 Ответ

5 голосов
/ 09 августа 2010

Вам также необходимо указать имя свойства проекции, например ...

.Add(Projections.Property("i.IncidentId"), "IncidentId")

, в общем случае вы не проецируете в один и тот же объект домена.Вы должны создать инцидент, например ...

public class IncidentDTO  
{
    public int IncidentID { get; set; }
    public DateTime CreationDatetime { get; set; } 
}

, а затем ...

.SetProjection(Projections.ProjectionList()
   .Add(Projections.Property("i.IncidentId"), "IncidentId")
   .Add(Projections.Property("i.CreationDatetime"), "CreationDatetime")
)
.SetResultTransformer(Transformers.AliasToBean<IncidentDTO>());

Если вы хотите, чтобы инциденты соответствовали некоторым критериям (не DTO), то неустановить проекции / преобразователь результата.Вместо этого вы просто делаете что-то вроде этого ...

IList<Incident> incidents = session.CreateCriteria<Incident>()
    .CreateAlias("Cause", "c")  //now you can access Cause properties via `c.`
    .Add(Restrictions.Eq("c.CauseDesc", "some cause")) 
    .List<Incident>();

Посмотрите, как объект корневого критерия не нуждается в псевдониме.Если это помогает, я использую только CreateCriteria для начального объекта.Если мне нужно сослаться на дочерние объекты, я использую CreateAlias.

...