Custom Lazy Loading Open Access ORM - vb.net

I'm working with open acces orm and I need a simple way to fetch just parent entity information and make a custom load of related children information. I mean when I ask for order I just want the orders information and to be able to load or not the orderlines information.
If I have:
Public Class Order
Public Property Number As Long
Public Property Description As String
Public Property OrderLines as List(of OrderLines) = new List(of OrderLines)
End Class
What can I do if I want for example:
Dim e as new EntitiesModel()
Dim q as Order = (from c in e.Orders
where c.Number = 5
select c).FirstOrDefault()
And I need that the query just to retrieve Order Data and not OrderLines, which seems what OA do by default.
Edit: I've already tried this:
Using dbcontext As New EntitiesModel()
Dim fetchStrategy As New FetchStrategy()
dbcontext.FetchStrategy = fetchStrategy
Dim q As Order
q = (From c In dbcontext.Orders
Where c.PK_Order = 79
Select c).FirstOrDefault
For Each olFound In q.OrderLines
Dim i As Integer
Console.WriteLN(olFound.Description&VbNewLine)
Next
End Using
I'm still receiving OrderLines data and I don't need that data always.Most of telerik's examples are about to load related data, but I want the opposite. Is there a way to specify wether I want or not to do it? I hope to be clear :/

You need to declare that the "OrderLines" should be lazy loaded. You could use the FetchPlans API or declare the association to be loaded lazily explicitly in the configuration.
If you using code-only mapping you can define the load behavior:
orderLineConfiguration.HasAssociation(x => x.Order).WithLoadBehavior(Telerik.OpenAccess.LoadBehavior.Lazy).WithOpposite(c => c.OrderLines);
The OrderLines will now be lazy loaded. Please refer to the documentation here and here.

Related

How to limit the properties needed for the view from the model

I am working very hard to understand the concept of Entity Framework and Models by building a new MVC Architecture Solution. I have started only with two Models that are identical to an (EXISTING DATABASE - That I must model after [Maybe comeback and re-factor later]), with a lot more models to come.
I get the data back to the VIEW no problem, however how do I scale down the CONTROLLER to only query items I need? In this example I have the code committed out (see below), but if I cast .ToList() it throws an exception because that is not the Model Type. I am sure I am missing something very simple, but I am stuck. Any help would be great.
VIEW
#ModelType IEnumerable(Of CompanyName.Models.QAs)
CONTROLLER
Private ReadOnly _db As New Context
Function Faq() As ActionResult
'Dim query As List(Of ShowFaqsModels)
'query = From f In _db.Faqs _
' Where Not f.Hk_DeletedDt.HasValue _
' Or f.Hk_DeletedDt = New DateTime(1900, 1, 1) _
' And f.Active = 1 _
' Order By f.CategoryId Descending _
' Select f.Question, f.Answer
Return View(_db.Faqs)
End Function
MODEL
Imports System.ComponentModel.DataAnnotations
Namespace Models
Public Class QAs
<Key>
Public Property QuestionId As Integer
Public Property CategoryId As Integer
Public Property Question As String
Public Property Answer As String
Public Property Active As Integer
Public Property Hk_CreatedDt As DateTime
Public Property Hk_ModifiedDt As DateTime
Public Property Hk_DeletedDt As System.Nullable(Of DateTime)
End Class
End Namespace
************ EDIT **********
CONTROLLER
Function Faq() As ActionResult
Dim faqs = From f In _db.Faqs _
Where Not f.Hk_DeletedDt.HasValue _
Or f.Hk_DeletedDt = New DateTime(1900, 1, 1) _
And f.Active = 1 _
Order By f.CategoryId Descending _
Select New FaqViewModel With {
.Question = f.Question,
.Answer = f.Answer
}
Return View(faqs)
End Function
Addition - Created a new Folder called "ViewModels" --- Did this to Only Use the Data need in the View.
VIEWMODELS
Imports System.ComponentModel.DataAnnotations
Namespace ViewModels
Public Class FaqViewModel
Public Property Question As String
Public Property Answer As String
End Class
End Namespace
Thanks again to the contributors on this. I am starting to figure out this puzzle and architect this solution. Yes yes I know you can separate out in to other projects, but this site is not needed for that.
Your model as you're describing it is your data model. The best practice for passing or accepting information to/from your view(s) is to use a new class as a view model. It will have only the information necessary for the view and nothing else.
The catch is that these are not always a 1 to 1 mapping (though some of might be). For example, my view models routinely have other information on them, such as collections required for dropdowns, boolean flags indicating if certain areas of the page should be rendered, api keys needed to passing along to javascript resources. It all depends on what your view's needs, but the ideas is that you give the view everything it requires, it should not have to go out and get it itself, unless there's no other way (which does happen in my experience).
Translating between data model and view model is something people have created specific tools for (like AutoMapper), just be aware that most rely on naming conventions of your object's properties being the same, and most would argue it's a bad practice to use an automapper-like solution for accepting information back from the browser.
You are trying to return "...(Select f.Question, f.Answer).ToList()" which would not result in a model of type CompanyName.Models.QAs.
Therefore either return the whole f.ToList() OR
Use ViewModels if you think that the Model has so many extra properties that you wont need all of them in your view. ViewModels are also like models but they are for your views in contrast with Models which basically reflect your database tables/relations in essence. If your view needs only 2 fields out of maybe 50 fields in your model than make a ViewModel for that view.

Linq where a record contains 2 matched fields

I’m working with an existing database with a design I’m not in control of, I’m using EF4, and querying using LINQ. I work in VB.Net but would be quite happy to translate a c# solution.
I would like to pull records from a table where two of the fields match a pair of items from a list.
So i have a list of
Public Class RequestInfo
Public Property INSP_ROUTINE_NM As String
Public Property FEATURE_ID As String
End Class
And I would like to query a table and pull any records where both INSP_ROUTINE_NM and FEATURE_ID match one of the Request Info items.
I can use contains easy enough on either of the fields
Dim Features = (From F In MLDb.TBL_FeatureInfoSet _
Where (C_Request.Select(Function(x) x.INSP_ROUTINE_NM)).Contains(F.INSP_ROUTINE_NM) Select F.FEATURE_ID, F.FEATURE_RUN_NO, F.INSP_ROUTINE_NM).ToList
I could use two contains calls but that would pull any record where both records match somewhere in the list not necessarily any one pair from the request.
You can try this:
C#
var Features= (from f in MLDb.TBL_FeatureInfoSet
let q = C_Request.Select(x=>x.INSP_ROUTINE_NM)
where q.Contains(f.INSP_ROUTINE_NM) || q.Contains(f.INSP_ROUTINE_NM)
// where q.Contains(f.INSP_ROUTINE_NM) && q.Contains(f.INSP_ROUTINE_NM)
select new {f.FEATURE_ID, f.FEATURE_RUN_NO}).ToList();

Need a concept on fetching data with HQL while three or more tables are in use

A small briefing on what I am trying to do.
I have three tables Content(contentId, body, timeofcreation), ContentAttachmentMap(contentId, attachmentId) and Attachment(attachmentId, resourceLocation).
The reason I adopted to create the mapping table because in future application the attachment can also be shared with different content.
Now I am using HQL to get data. My objectives is as follows:
Get All contents with/without Attachments
I have seen some examples in the internet like you can create an objective specific class (not POJO) and put the attribute name from the select statement within its constructor and the List of that Class object is returned.
For e.g. the HQL will be SELECT new com.mydomain.myclass(cont.id, cont.body) ..... and so on.
In my case I am looking for the following SELECT new com.mydomain.contentClass(cont.id, cont.body, List<Attachment>) FROM ...`. Yes, I want to have the resultList contain contentid, contentbody and List of its Attachments as a single result List item. If there are no attachments then it will return (cont.id, contentbody, null).
Is this possible? Also tell me how to write the SQL statements.
Thanks in advance.
I feel you are using Hibernate in a fundamentally wrong way. You should use Hibernate to view your domain entity, not to use it as exposing the underlying table.
You don't need to have that contentClass special value object for all these. Simply selecting the Content entity serves what you need.
I think it will be easier to have actual example.
In your application, you are not seeing it as "3 tables", you should see it as 2 entities, which is something look like:
#Entity
public class Content {
#Id
Long id;
#Column(...)
String content;
#ManyToMany
#JoinTable(name="ContentAttachmentMap")
List<Attachment> attachments;
}
#Entity
public class Attachment {
#Id
Long id;
#Column(...)
String resourceLocation
}
And, the result you are looking for is simply the result of HQL of something like
from Content where attachments IS EMPTY
I believe you can join fetch too in order to save DB access:
from Content c left join fetch c.attachments where c.attachments IS EMPTY

fetch single property in object from database

I am working on NET MVC 3.0 and Nhibernate 3.0. I want to fetch only one property from database to an object.
For instance, suppose I have a class Module. I want to select all the names from module table (like select modulename from module query) and an prepare a list of module objects which have only name. All other properties can be null.
I tried this using QueryOver API:
IQueryOver<ProjectModule> module = session.QueryOver<ProjectModule>()
.Select(a=>a.Name)
.TransformUsing(
NHibernate.Transform.Transformers.AliasToBean<ProjectModule>());
pm = module.List<ProjectModule>();
pm is IList<ProjectModule> type.
Transaction gets committed successfully. No error occurred, but I get a list of module objects with all properties = null. Module name null, module id null etc.
I checked what query is executing on SQL using NUnit and got this: SELECT this_Name as y0_ FROM ProjectModule this_.
To be more accurate create a DTO object, assume ProjectModuleDto, that will contain only the Name. It's not a good practice to use the the domain object with uninitialized values through your code, cause it creates confusions of filled data in various scenarious.
And the fllowing code will do the trick - populate the list of DTOs: ProjectModuleDto with correct Name of project module from database:
ProjectModuleDto projectModuleDto = null;
IQueryOver<ProjectModule> module = session.QueryOver<ProjectModule>()
.SelectList(
list=>list.Select(a => a.Name).WithAlias(() => projectModuleDto.Name)
)
TransformUsing(NHibernate.Transform.Transformers.AliasToBean<ProjectModuleDto>());
pm = module.List<ProjectModuleDto>();
If you are fetching only a single property, you don't need to use transformers. Try to use a List<string> directly:
var moduleNames = session.QueryOver<ProjectModule>()
.Select(a => a.Name)
.List<string>();
Read more about QueryOver syntax on NHibernate blog.
Is this what you're looking for?
List<ProjectModule> result = new List<ProjectModule>();
session.QueryOver<ProjectModule>()
.Select(a => a.Name)
.ToList().ForEach(delegate(string mName)
{
result.Add(ProjectModule() { Name = mName });
});

Entity Framework 4.2 table per hierarchy group by discriminator

I am working on a project using an EF 4.2 code first model. This model contains a TPH inheritance structure for products. I need to group the polymorphic results of this inheritance model on the discriminator and am running into some issues.
The entity framework does not expose the discriminator to complete this grouping. My first question is can I get direct access to this discriminator? My reading and experience is telling me no, so I came up with this solution that sort of works. It is not performing well and I am not happy with how it will need to be maintained.
My classes look something like this (simplified):
Public MustInherit Class Product
<key()>
Public Property ProductID as integer
<StringLength(50, ErrorMessage:="Max 50 characters")>
<Required(ErrorMessage:="Product name is required")>
Public Property Name as String
<TimeStamp()>
Public Property Time_Stamp as DateTime = DateTime.Now()
End Class
Public Class Desktop
Inherits Product
<StringLength(50, ErrorMessage:="Max 50 characters")>
<Required(ErrorMessage:="Processor is required")>
Public Property Processor as String
End Class
Public Class Monitor
Inherits Product
<Required(ErrorMessage:="Monitor size is required")>
Public Property Size_Inches as Integer
End Class
I built an extension method that takes a product and returns it's basetype name as a string.
<Extension()>
Public Function ProductType(ByVal inProduct as Product) as String
ProductType = inProduct.GetType().BaseType.Name
End Function
With that, I built this structure to group the results of product by type so I can run through them:
Dim tmpProducts = db.Products.ToList()
Dim GrpProducts = tmpProducts.GroupBy(Function(prod) prod.ProductType) _
.Select(Function(s) New With {.ProductType = S.Key,
.Products = S })
I can now loop through the list to get the behavior I want, but the performance is not ideal and I am concerned it will be unacceptable as the number of products grows.
For Each ProductGroup in GrpProducts
Dim TypeName as String = ProductGroup.ProductType
Dim TypeProducts = ProductGroup.Products
Next
Also, this can give me easy access to shared properties (Name) but now I don't have many options to cast these into their real type, maybe a select case around TypeName. . .
Any recommendations are appreciated, also please forgive any code errors above, I retyped the examples from memory as I don't have access to the project at the moment.
A solution would be to model a bit more, and have a new entity ProductType having a property Name. Then you would have a simple 1-N relationship between Product and ProductType. I have not used EntityFramework, but with NHibernate you could easily make the framework always join that table on queries, so that it would not return a proxy for ProductType for each Product, which could harm performance.
As an add-on, in the future ProductType could develop other interesting properties (such as values that are common for every Product of that ProductType), so it adds flexibility to your solution, although it does have the immediate cost of adding another table to your database.
Following Linq query should get you a way to solve group by discriminator
from a in db.Records
group a.ID by new
{
Name= a is Audio ? "Audio" :
a is Video ? "Video" :
a is Picture ? "Picture" :
a is Document ? "Document" : "File"
} into g
select new
{
Name = g.Key.Name,
Total = g.Count()
}