In my product entity i have the following property. It works correctly and returns back the number of stock available. Looking at my profiler i can see that this statement is called everytime i call the product entity which is causing performance issues. Is there a way i can only call this property when needed. I've added 'lazy=true' but it is still called everytime. I'm using nhibernate 2. I'd prefer not to upgrade if poss.
<property name="StockAvailable" lazy="true" type="Int32" formula="(SELECT Stock - isnull((select Sum(oi.Quantity) from OrderItems oi inner join Orders o on oi.OrderId = o.Id where (oi.OrderItemStatusId = 0 or oi.OrderItemStatusId = 1) and o.OrderStatus = 3 and oi.ProductId = Id), 0))"/>
Lazy properties are only supported from NHibernate 3 and up, so you need to upgrade if you want that property to be on your entity.
Another possiblity is to create an entity which is lazy-loaded and has just this single property on it (you could even map it to the same table).
I don't know if this is an issue to you, but you should also consider creating a view for that calculation which uses group by. This is important if you want to load not a single but many entities at the same time as group by usually performs mich better than a subselect.
http://ayende.com/Blog/archive/2010/01/27/nhibernate-new-feature-lazy-properties.aspx
Looking at the date I don't think that made it into 2.1.2, since that was released in nov 2009.
Related
Every article I need to solve my problem seems to be in C# and I need a solution in VB.NET.
I'm using EF 6.0 with Database First model. Let me use the classic Customer product scenario to demonstrate my situation. In my database I have three tables Customer, Product and CustomerProduct. See this example in this link as mine is exactly the same.
After I generate my model from the database, my entity model diagram shows that the CustomerProduct has disappeared as expected and the the model shows a many to many relationship between Customer and Product also as expected with navigational properties of Products in Customer and Customers in Product.
All I want to do is find the product related to a customer pull out some data from both tables namely CustName and ProductName.
The SQL I would use is:
SELECT c.CustName, p.ProductName FROM Customer c
INNER JOIN CustomerProduct cp on c.CustomerId = cp.CustomerId
INNER JOIN Product p on cp.ProductId = p.ProductId
WHERE c.CustomerId=101
I don't know how to use the Addresses navigational property to access the Address data in one query.
You include them and then access them via the property in the Entity class.
Dim query = model.User.Include("Address").Include("UserAddressLink").Where(Function(o) o.UserId = 101).FirstOrDefault
If Not query Is Nothing Then
Dim houseNumber = query.Address.HouseNo 'uses the navigation property
End If
Thanks to InteXX I managed to work it out. This is my whole solution
Using db as new CustProdEntities
Dim query = db.Customers.Include(Function(U) U.Products).ToList
txtCustomer.Text = query.First.CustName
txtProduct.Text query.First.Products.First.ProdName
End Using
The bit I was stuck on was having to filter twice to the Product data. I'm not sure if there's an easier way to do this but it works for now.
I am developing a MVC3 application in c# and I am using NHibernate for the ORM part. I need to generate a list of all registered customers and their latest order. On the application side, this would require to go through all customers and retrieve all their orders to extract the latest one.
Unneeded overhead, isn't it?
On the database, I could create a view and model the entity accordingly, but then I cannot create new customers due to the fact that populating a view is not possible. So, any ideas or best practices how you solved such issues? Here's a sql query that would serve the needed information:
SELECT c.id, c.name, c.description, m.ordernumber AS latest_order, m.unixtime, m.id AS latest_order_id
FROM dbo.customer c
LEFT JOIN dbo.mailorder m ON c.id = m.customer_id
WHERE m.unixtime = (SELECT MAX(unixtime) FROM dbo.mailorder)
Any help is very much appreciated!
Best regards,
Martin
You can use formula to get last order for customer, something like this:
<property name="LatestOrder" formula="(SELECT MAX(dbo.mailorder.unixtime) FROM dbo.mailorder where dbo.mailorder.customer_id = ID)" />
I am trying to use Projections to Create a DTO from a Lead class. My DTO has, for example, a Home phone number, a mobile number and an email address, but the Lead Class has a collection of contact details. So I'm trying to find a way to retrieve each contact detail so that I can set the properties on the dto. I have tried using sub queries and projections but to no avail.
The SQL I'm trying to generate is something like this:
SELECT
A.LeadId,
B.ContactId,
B.Value,
C.ContactId,
C.Value,
D.ContactId
FROM Lead A
LEFT JOIN ContactDetail B ON A.LeadId=B.LeadId AND B.ContactType='Home Number'
LEFT JOIN ContactDetail C ON A.LeadId=C.LeadId AND C.ContactType='Mobile Number'
LEFT JOIN ContactDetail D ON A.LeadId=D.LeadId AND D.ContactType='Email Address'
So in short I'm trying to join to the same table 3 times based on different criteria, and I know that in NHibernate I can't use CreateAlias to join to the same table more than once and I'm anxious to know if this is possible using either the Criteria API or NHIbernate Linq. Thanks in advance for any help.
I would load the "regular" lead instance from nHibernate with its contact detail collection. Then I would use AutoMapper, to map it to the DTO class.
In my opinion, this is a much cleaner approach since you do not create special data access methods just for "simple" DTO mappings. And it's easier for refactoring since everything is expressed via "c sharp code".
Link to AutoMapper
I've seen model defined functions used in in-code queries (queries written by the developer using Linq etc) and I'm wondering if there's any way to map a model-defined function to an entity property so that EF4 will automatically query the database using it.
For example:
Suppose I have a Product class and an Order class and that Product has a TotalSold property. Ideally I would like to create a model defined function like:
select sum(o.quantity) from order, product where o.productid = product.productid
and bind that to the TotalSold property of Product so that every query for a given Product would auto generate an inner select that would populate the TotalSold property.
Does this make sense? Is it possible?
I found a good-enough solution and blogged about it at http://statichippo.com/archive/2011/01/26/Mapping-a-computed-property-in-EF4.aspx
When using NHibernate and lazy loading, how would I get this kind of behavior:
I have a Customer class, and the customer has many addresses (say 100 to make this make more sense).
I load my customer row, I want to just access 3 items from the addresses collection.
I don't want nHibernate to load all 100 addresses, but with lazy loading from what I understand, will load all of them?
I want 3 of them only, and I want to load all 3 at once, how would I get this behavior?
It depends on
if you need "just one" or a certain one
if you need the other items in the list later in the same session
You can use
filters to filter the collection. These filters are defined in the mapping file and activated and parameterized when using the session
AliasToEntityMap result transformer which lets you filter the collection within a query
batch fetching that fetches a certain amount of elements at once.
<class name="Customer">
<set name="Address" batch-size="3">
...
</set>
</class>
I think Lazy Loading will not help you here. I would take this responsibility to the AddressDataProvider. You will get a collection of addresses based on the customer and other predicates (I think first address doesn't have any business value. One more thing first can vary. The order in which addresses are returned is arbitrary.)
- The last visited address.
- The closest address to the customer address.
- The latest (added) address
etc.
Address GetLastVisited(Customer c);
Address GetClosest(Customer c);
Just my 2 cents.
It's possible to add batch size, but making batch size to small you may end up having many database calls when iterating over them.
You could populate the collection using HQL or a Criteria which would only select 1 address, however then you won't be able to access the other addresses unless you reload the entity.
Worst case, you would need the Hibernate "with" keyword, which wasn't implemented in NHibernate.
Is there a Common Criteria for these records you want to see?. (For Eg: Something like the current Addresses?. (say Current addressFlag = 1 ?)
If that is the case, then you can use a Where Clause on the collection mapping.
eg:
<bag name="Addresses" where="CurrentAddressFlag = 1" cascade="save-update" fetch="select" lazy="true">
<key column="AddressId"/>
<one-to-many class="Address"/>
</bag>