如果可选,为什么我需要为我的投影设置别名?

Mik*_*ike 4 nhibernate castle-activerecord

我正在阅读有关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; }
}
Run Code Online (Sandbox Code Playgroud)

这是我用来查询数据库的内容.

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);
Run Code Online (Sandbox Code Playgroud)

除非我设置了别名,否则两个投影属性都不会填充.所以我的问题是,为什么别名是可选的?我确定我只是遗漏了别的东西.但是如果我输入一个随机别名(例如abc),它将返回一个错误,说它在Incident类中找不到属性"abc".很公平,我添加了适当的别名来匹配我的属性名称.瞧!我的属性现在正在填充属性.

现在出现了我想查询查询表的问题.我加

.Add(Projections.Property("c.CauseDesc"), "CauseDesc")
Run Code Online (Sandbox Code Playgroud)

到我的ProjectionList并追加

.CreateCriteria("i.Cause", "c")
Run Code Online (Sandbox Code Playgroud)

但现在它抱怨它无法从我的事件模型中找到"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>();
Run Code Online (Sandbox Code Playgroud)

这确实创建了一个有效的查询(我使用分析器检查了它),但它似乎在填充我的通用列表时出现问题.它给了我错误"值\"System.Object [] \"不是类型\"oms_dal.Models.Incident \",并且不能在此通用集合中使用.\ r \nParameter name:value".但是,如果我不使用投影但是它选择了50多个我不想要的字段,那么一切正常.这是否意味着我在这种情况下被迫使用DTO?

dot*_*joe 5

您需要指定投影属性名称,如...

.Add(Projections.Property("i.IncidentId"), "IncidentId")
Run Code Online (Sandbox Code Playgroud)

另外,通常您不会投射到同一个域对象中.你应该创建一个像...一样的事件

public class IncidentDTO  
{
    public int IncidentID { get; set; }
    public DateTime CreationDatetime { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

然后...

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

如果您希望事件符合某些条件(不是DTO),则不要设置projection/resulttransformer.相反,你只是做这样的事......

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>();
Run Code Online (Sandbox Code Playgroud)

了解根条件对象如何不需要别名.如果它有帮助,我只使用CreateCriteria作为初始对象.如果我需要引用子对象,我使用CreateAlias.