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

发布于 2024-09-13 04:36:26 字数 2546 浏览 1 评论 0原文

我正在阅读有关 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”。公平地说,我添加了适当的别名来匹配我的属性名称。瞧!我的房产现在正在填充房产。

现在出现了我何时想要查询查找表的问题。我添加

.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参数名称:值”。但是,如果我不使用投影,则一切正常,但它会选择 50 多个我不想要的字段。这是否意味着我在这种情况下被迫使用 DTO?

I'm reading the documentation about DetachedCriteria. The documentation clearly shows that setting an alias for your projection is optional. However, whenever I omit the alias my model properties contain no data. Here are my two test models.

[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; }
}

Here is what I use to query the database.

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);

Both projections properties do not get populated unless I set an alias. So my question is, why is the alias optional? I'm sure I'm simply missing something else. But if I put a random alias (e.g. abc) it'll return an error saying that it could not find property "abc" in the Incident class. Fair enough, I add the appropriate alias to match my property names. And voila! My properties are now property being populated.

Now comes the issue of when I want to query a lookup table. I add

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

to my ProjectionList and append

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

But now it complains that it can't find "CauseDesc" from my Incident model.

What am I missing from this whole criteria ordeal?

Update:
The following code

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>();

This does create a valid query (I checked it with a profiler) but it seems to be having issues populating my generic list. It gives me error "The value \"System.Object[]\" is not of type \"oms_dal.Models.Incident\" and cannot be used in this generic collection.\r\nParameter name: value". However, all works fine if I don't use a projection but then it selects 50+ fields which I don't want. Does that mean I'm forced to use a DTO in this circumstance?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

‘画卷フ 2024-09-20 04:36:27

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

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

此外,通常您不会投影到同一域对象中。您应该创建一个事件 dto,例如...

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。

You need to specify the projection property name like...

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

also, in general you do not project into the same domain object. You should create an incident dto like...

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

and then...

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

If you want Incidents matching some criteria (not a DTO), then don't set projections/resulttransformer. Instead you simply do something like this...

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>();

See how the root criteria object doesn't need an alias. If it helps, I only use CreateCriteria for the initial object. If I need to reference child objects, I use CreateAlias.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文