开发者

Selecting only a few columns from a table

I had problems using c#, nhibernate and link. In the example bellow, I do a SELECT in the BrandTable, but I need only the "Name" and "Id" columns. But it always do a select with all columns of the table. Using EntityFramew开发者_如何学Goork, the same code bellow generates a select with only this two columns.

How to do this in nhibernate?

 using (ISession session = MyConnection.GetCurrentSession())
        {
            var brands = from b in session.QueryOver<BrandTable>().List()
                                 orderby b.Name
                                 select new Brand {Id = b.id, Name = b.Name};

            return brands.ToList();
        }


You can't use query comprehensions with QueryOver, because it is not a Linq provider. In your example you're actually selecting all records, and then using LINQ to Objects. Add the NHibernate.Linq namespace to your file and rewrite the query as

from b in session.Query<BrandTable>()
orderby b.Name
select new Brand {Id = b.id, Name = b.Name};


This is an example using projection:

List results = session.CreateCriteria<BrandTable>()
.SetProjection( Projections.ProjectionList()
     .Add( Projections.Id(), "Id" )
     .Add( Projections.Property("Name"), "Name" )
)
.SetResultTransformer(Transformers.AliasToBean<BrandTable>()); // edit - don't forget the result transformer! 
.List();

here an example using QueryOver:

NHibernate QueryOver select entity and aggregates

[edit] also, there is currently a bug when caching icriteria projections. (if you try to cache the query, you get an exception) https://nhibernate.jira.com/browse/NH-1090 [/edit]


Releted posts:

NHibernate Criteria: howto exclude certain mapped properties/collections?

Only retrieve specific columns when using Critera queries?

LINQ-NHibernate - Selecting only a few fields (including a Collection) for a complex object


to make your queries refactor-safe (no 'magic strings'), you can implement something like so:

public static class ObjectExtensions
{
    public static string NameOf<T>(this T target, Expression<Func<T, object>> propertyExpression)
    {
        MemberExpression body = null;
        if (propertyExpression.Body is UnaryExpression)
        {
            var unary = propertyExpression.Body as UnaryExpression;
            if (unary.Operand is MemberExpression)
                body = unary.Operand as MemberExpression;
        }
        else if (propertyExpression.Body is MemberExpression)
        {
            body = propertyExpression.Body as MemberExpression;
        }
        if (body == null)
            throw new ArgumentException("'propertyExpression' should be a member expression");

        // Extract the right part (after "=>")
        var vmExpression = body.Expression as ConstantExpression;

        // Extract the name of the property
        return body.Member.Name;
    }

}

using it like this:

MyEntity entity = null; // don't need a 'valid' instance.
string propName = entity.NameOf(x => x.SomePropertyName);


You can also do this with QueryOver in NH. Below is taken from http://nhforge.org/blogs/nhibernate/archive/2009/12/17/queryover-in-nh-3-0.aspx

Projections

Simple projections of the properties of the root type can be added using the .Select method which can take multiple Lambda Expression arguments:

IList selection =
    session.QueryOver<Cat>()
        .Select(
            c => c.Name,
            c => c.Age)
        .List<object[]>();

Because this query no longer returns a Cat, the return type must be explicitly specified. If a single property is projected, the return type can be specified using:

IList<int> ages =
    session.QueryOver<Cat>()
        .Select(c => c.Age)
        .List<int>();

There are several more examples of how to use projections in the link above.


You can select some column for one domain using the following step:

  1. Create a small class with the fields that you wants: Example:

 private class LeadInformation
  {
            public string Id { get; set; }
            public DateTime AdmissionDate { get; set; }
  }

  1. Query the domain entity where do you want to extract the information

 IQueryable leads =
                repository.Query()
                .Where(x => x.AdmissionRepUserObj.ID.ToString() == filter.UserId
                    ).Select(lead => new LeadInformation 
                     {AdmissionDate = lead.DateApplied.Value,
                     Id = lead.ID.ToString()});

In the example Lead is the entity that we want to extract the information. Observe that the destination is of the same type of the target class LeadInformation. This return a queryable list of target class LeadInformation with only two column of the source domain class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜