LINQ Modelling Automagically Retrieving Data Via EntityRef - asp.net-mvc

I'm using LINQ to model my database, but I'm writing it by hand (Steve Sanderson recommends this in his ASP.NET MVC book). What I need to know is what's happening when you create an EntityRef, and how it's referenced. If I create my queries manually (without using LINQ), but use LINQ to model it, and I bring back just the ID of something, then reference the actual table column using EntityRef in the view, does it do the join, or does it re-query the database for that bit of information?
To clear things up, if I have this in my repository:
public IEnumerable<MyTable> ListMyTable(int? myColumnVar)
{
string query = "SELECT * FROM MyTable WHERE MyColumn = {0}";
return this.ExecuteQuery<MyTable>(query, myColumnVar);
}
and then in my controller I do this:
IEnumerable<MyTable> mytables = _contractsControlService.ListMyTable(1);
return View(mytables);
then in my view I do things like
<%=tbl.Ref.MyColumn %>
I'm referencing something set out by the LINQ model, but isn't actually in the table output. How does it get that data?
To clear things up further, we're using systems which require ultimate speed, so the LINQ-to-SQL is too slow for us, hence why we're using direct queries in our repository. I wouldn't mind using this EntityRef business if only I knew what was happening underneath.

You have most likely used the Object Relational designer to create an entity class for the Ref entity and an association between the MyTable and the Ref entity. You can also do that manually by creating the appropriate entity classes and using attributes to map the classes to the database schema. You can read the details in How to: Customize Entity Classes by Using the Code Editor (LINQ to SQL) on MSDN.
In your generated (or handwritten) code you will find some attributes:
[Table(Name="dbo.Ref")]
public partial class Ref : INotifyPropertyChanging, INotifyPropertyChanged
and
public partial class MyTable: INotifyPropertyChanging, INotifyPropertyChanged
{
[Association(Name="Ref_MyTable", Storage="_Ref", ThisKey="RefId",
OtherKey="Id", IsForeignKey=true)]
public Ref Ref
{
get
...
The entity classes combined with the attributes enables the Linq-to-Sql framework to retrieve entity classes directly from the database.
If you want to monitor the SQL genereated by Linq-to-Sql you can assign the DataContext.Log property:
context.Log = Console.Out;
In your example, navigating from MyTable to Ref, probably generates SQL along these lines:
SELECT Id, Field1, Field2, Field3
FROM Ref
WHERE Id = #RefId

Related

Best practices with DTOs in ASP.NET MVC Entity Framework

What's the most preferred way to work with Entity Framework and DTOs?
Let's say that after mapping I have objects like:
Author
int id
sting name
List<Book> books
Book
int id
string name
Author author
int authorID
My DTOs
AuthorDTO
int id
sting name
BookDTO
int id
string name
int authorID
Since author can have a lot of books I don't want to retrieve all of them, when for example I'm only interested in authors.
But sometimes I might want to get few authors and filtered books or all books.
I could go with multiple queries AuthorDTO GetAuthor(int id) List<BookDTO> GetBooks(int authorID). But that means several accesses to database.
The ways I see it:
If I had in AuthorDTO field List<BookDTO> books the job could be done. But sometimes I would keep this list empty, if for example I listed only authors. And that means some unconsistency, mess and a lot of details to remember.
Return Tuple<AuthorDTO, List<BookDTO>> it might be a bit confusing.
Define new DTO.
AuthorAndBooksDTO
AuthorDTO author
List<BookDTO> books
The problem with sticking to a sinlge AuthorDTO and selectively filling the List is that you are now forced to keep track of where that DTO came from. Is the list of Books not hydrated, or does this Author simply have no books? Do I have to go back to my controller and call a different method to get a different state of the same DTO? This lacks clarity from the consumer's standpoint.
In my experience, I've leaned the way of more DTOs instead of trying to re-use a set of basic DTOs to represent multiple different sets of data. It requires a bit more "boilerplate", having to set up a whole bunch of similar DTOs and mappings between DTO and Entity, but in the end the specificity and clarity makes the codebase easier to read and manage.
I think some clarification of the issues involved will actually solve your confusion here.
First and most importantly, your entity classes are DTOs. In fact, that's all they are. They're classes that represent a table structure in your database so that data from queries Entity Framework makes can be mapped on to them. In other words, they are literally objects that transfer data. The failing of Microsoft and subsequently far too many MVC developers is to conflate them with big-M Models described by the MVC pattern.
As a result, it makes absolutely zero sense to use Entity Framework to return one or more instances of an entity and then map that to yet another DTO class before finally utilizing it in your code. All you're doing is creating a pointless level of abstraction that adds nothing to your application but yet another thing to maintain.
As far as relationships go, that's where Entity Framework's lazy/eager loading comes in. In order to take advantage of it, though, the property representing the relationship must follow a very specific convention:
public virtual ICollection<Book> Books { get; set; }
If you type it as something like List<Book>, Entity Framework will not touch the relationship at all. It will not ever load the related entities and it will not persist changes made to that property when saving the entity back to the database. The virtual keyword allows Entity Framework to dynamically subclass your entity and override the collection property to add the logic for lazy-loading. Without that, the related entities will only ever be loaded if you explicitly use Load from the EF API.
Assuming your property is defined in that way, then you gain a whole world of abilities. If you want all books belonging to the author you can just interact with author.Books directly (iterate, query, whatever). No queries are made until you do something that requires evaluation of the queryset. EF issues just-in-time queries depending on the information you're requesting from the database. If you do want to load all the related books at the same time you retrieve the author, you can just use Include with your query:
var author = db.Authors.Include(m => m.Books).SingleOrDefault(m => m.Id == id);
My first question would be to ask why you are creating DTO's in the first place? Is there a consumer on the other end that is using this data? Is it a screen? Are you building DTO's just to build DTO's?
Since you tagged the question as MVC i'm going to assume you are sending data to a view. You probably want a ViewModel. This ViewModel should contain all the data that is shown on the View that uses it. Then use entity framework to populate the view model. This may be done with a single query using projections or something complex.
So after all that blathering. I would say you want option 3.
Just like the others said, for clarity reasons, you should avoid creating "generic" DTO's for specific cases.
When you want to sometimes have authors and some of their books then model a DTO for that.
When you need only the authors then create another DTO that is more suited for that.
Or maybe you don't need DTOs, maybe a List containing their names is enough. Or maybe you could in fact use an anonymous type, like new { AuthorId = author.Id, AuthorName = author.Name }. It depends on the situation.
If you're using ASP.NET MVC the DTO you'll want is in fact a ViewModel that best represents your page.
Based on what you've described, you're view model could be something like this
public class BookViewModel{
public int Id {get;set;}
public string Name {get;set;}
}
public class AuthorViewModel{
public int Id {get;set;}
public string Name {get;set;}
public List<BookViewModel> Books {get;set;} = new List<BookViewModel>();
}
public class AuthorsViewModel
{
public List<AuthorViewModel> Authors {get;set;} = new List<AuthorViewModel>();
//add in this class other properties, like the filters used on the page...
public void Load(){
//here you can retrieve the data from your database.
//you could do like this:
//step 1: retrieve data from DB via EF
//step 2: fill in the Authors view models from the data at step 1
}
}
//and in your controller you're calling the Load method to fill you're viewmodel with data from db.
public class AuthorsController{
public ActionResult Index(){
AuthorsViewModel model = new AuthorsViewModel();
model.Load();
return View(model);
}
}

Joining tables from two databases using entity framework

I am working on an ASP.NET MVC 4 web application. I am using Entity Framework as the data access layer, using database first approach (.edmx file).
Currently I have a problem in join tables that are defined inside two different databases (i.e. I have two .edmx files).
For example if I want to join tables I am performing the following query:-
public ActionResult AutoComplete(string term)
{
var tech = repository.AllFindTechnolog(term).Take(100);//Call to the first database
var resources = repository.GetResources(tech.Select(a => a.IT360ID.Value).ToArray(), false);//call to the second database
var query = from techItems in tech
join resourcesItems in resources
on techItems.IT360ID.Value equals resourcesItems.RESOURCEID // join based on db2ID
orderby techItems.PartialTag
select new //code goes here
return Json(query, JsonRequestBehavior.AllowGet);
}
I will have two separate calls to the database, and a join inside the application server, which is not the best performance-oriented solution. Ideally the joins will happen completely inside the database engine.
I know that a stored procedure will allow me to join tables from different databases purely on the server, but I do not want to use SP because it will make my code less maintainable and less testable.
So I am searching for a solution where I can do the join using entity framework and to result in a single database join?
If you want to do it with a single database call you will have to create a View in the database that joins the 2 tables from separate db's. Once the view is created you can add it to EF as a single object, which you can manipulate further and Query off of. The view will basically be a table and it will be easily maintable and easy to bind to a strongly typed model
Another way ,similiar like you have posted, you can query separate .edmx files and then join them.
Yes, there is 2 calls to the database but it shouldn't be that expensive and probably won't notice a difference.
using(var db = new MyEntities())
using (var db2 = new MyEntities2())
{
var one = db.Table1.AsEnumerable();
var two = db2.Table2.AsEnumerable();
var result = from o in one
join t in two on o.Id equals t.Id
// blah blah
}
#CSharper's answer is close. As #Oliver mentioned in the comments, IEnumerable loads the table into application memory, leading to crashes if you have a large database.
The solution is to use IQueryable, which can be called with LINQ - this produces SQL which is much faster.
// This is a generic method, modify to your needs
public ActionResult Details(int? id)
var one = db.Table1.AsQueryable();
var two = db2.Table2.AsQueryable();
// since you're using MVC EF, I assume you want to put this in a viewmodel
// (in this case ObjectCombined)
// assume "id" is passed as parameter
Object1 result1 = (from o in one where one.id == id select o).Single();
Object2 result2 = (from t in two where t.id == o.id select t).Single();
ObjectCombined result = new ObjectCombined(result1, result2);
return View(result);
}
Might I suggest that you look into using a synonym in your database. For instance, you can create a synonym to the resources table in the database that your tech table is located. This will ensure that you will not need to maintain 2 EDMX files. Instead you can have a single EDMX file and you can simply join your tech table to the synonym of the resource table and voila - you are on your way.
UPDATE: Please note that if you are using synonyms there is an extra bit of work you will need to do to the EDMX file to get it working in Entity Framework. Here is a blog post that was put out by a programmer who got it to work. Here is the original stackoverflow question she asked.
HAPPY CODING!!! :)
you can create a view or a stored procedure, your sql statement can then make cross db query just make sure your credentials can DML or DDL on both db. otherwise try the nested using entities that will make sure you will not get the linq bug when you dont declare the db entity inside a using statement.

How can I create and use views using EF6 Code First?

Is there actually any official strategy for creating and using views with EF6.1 Code First? I can reverse the database into Code First and get tables not views. I can import the database into Model First and get views and then do Generate DB from Model and my edmx is modified and the views are converted to tables. MSFT seems to have all but abandoned Model First, and the new Update 2 seems to have reverse engineering for Code First so I feel forced to convert to Code First but has the EF team given support for any reasonable approach to using views or stored Procedures in Code First? After all CF is supposed to create the DB but what - are you no longer supposed to use either of these SQL Server features in a .NET EF application?
For starters you can use views and stored procedures that are already created in the database. For views you don't have to do any mapping if you create a code like this:
public TestContext : DbContext
{
public DbSet<User> AdminUsers { get; set; }
}
And you have a view in the database named dbo.AdminUsers and it can be mapped to the class User (contains all required properties with the same name as the property).
For stored procedures you can use the SqlQuery function either through the Database property of the DbContext such as:
var userActivityReport = context.Database.SqlQuery<UserActivityReport>(
"dbo.GetUserActivityReport #p0, #p1", startDate, endDate);
Or through the SqlQuery function of the DbSet class:
var newUsers = context.Users.SqlQuery("dbo.GetNewUsers #p0", count);
If you want to create, modify or delete views and stored procedures via Entity Framework you can either use custom migration operations see http://dolinkamark.wordpress.com/2014/05/03/creating-a-custom-migration-operation-in-entity-framework/
For event better integration you can use the Public mapping API with a library provided by a community member: https://codefirstfunctions.codeplex.com/

How do I use a stored Procedure to return a single entity in Entity Framework 4?

New to Entity Framework .Using EF4. I have found articles and managed to use stored procedures to return a list of entities.
But cannot see/work out how you return a single entity.
Given that I have a stored procedure "GetCustomerById" that return a single customer How do I map it?
Using the Model Browser I right click on "Function Import" and I have added my StoredProcedure
however whatever I select does not seem to return a "Single Entity"
Am I missing the obvious?
thanks a lot for any link or suggestions
When you do Function Import you need to select the entity your SP returns from the drop down (i.e. Customer). The catch is EF does NOT directly returns Customer object as per your selection but System.Data.Objects.ObjectResult which implements IEnumerable.
To be more specific, here is the generated code for your function:
public ObjectResult<Customer> GetCustomerById(Nullable<global::System.Int32> Id)
That's because EF has no idea if your SP returns a single record or a list of them so it wraps the result inside ObjectResult. You can enumerate through this to get your Customer entity like any other IEnumerable object. For example:
Customer myCustomer = context.GetCustomerById(1).First();

Entity Framework testing with IRepository - problem with lazy loading

I am refactoring an MVC project to make it testable. Currently the Controller uses the Entity Framework's context objects directly to ask for the required data. I started abstract this and it just doesn't work. Eventually I have an IService and an IRepository abstraction, but to describe the problem let's just look at the IRepository. Many people advise an interface with functions which return some of these: IQueriable<...>, IEnumerable<...>, IList<...>, SomeEntityObject, SomeDTO. Then when one wants to test the service layer they can implement the interface with a class which doesn't go to the database to return these.
Problem: Using linq to entities I have lazy (deferred) loading in my toolset. This is actually very useful, because my controller action functions know which data they need for the view and I didn't ask for more than required. However linq to anythingelse doesn't have lazy loading. So when my IRepository functions return any of the above mentioned things I lose lazy loading. I extended my interface with functions like "GetAnything" and "GetAnythingDeep" but it's not enough: it has to be much more fine-grained. Which would result about 5-6 functions for the same type of object, depending on the properties I want to get in the result. Maybe could be a general function with some "include properties" parameter, but I don't like that too.
Eventually atm I think if I want to make it testable that will result either much less efficient or much more complicated code. Sounds not right.
Btw I was thinking about to change the data source behind the entity model to either xml or some object data soruce, and so I could keep the linq to entities. I found that it's not supported out of the box... which is also sad: this means that entity framework means database source - not a really useful abstraction.
Specific example:
Entity objects:
Article, Language, Person. Relations: Article can have 1-N languages, and one Person (publisher).
ViewModel object:
ArticleDeepViewModel: Contains all the properties of the article, including the languages and the Name of the Person (it's for view the article, so no need for the other properties of the person).
Controller action which will return this view should get the data from somewhere.
Code before modifications:
using (var context = new Entities.Articles())
{
var article = (from a in context.Articles.Include("Languages")
where a.ID == ID
select new ViewArticleViewModel()
{
ID = a.ID,
Headline = a.Headline,
Summary = a.Summary,
Body = a.Body,
CreatedBy = a.CreatedByEntity.Name,
CreatedDate = a.CreatedDate,
Languages = (from l in context.Languages select new ViewLanguagesViewModel() { ID = l.ID, Name = l.Name, Selected = a.Languages.Contains(l) })}).Single();
this.ViewData.Model = article;
}
return View();
Code after modifications could be something like:
var article = ArticleService.GetArticleDeep(ID);
var viewModel = /* mapping */
this.ViewData.Model = viewModel;
return View();
Problem is that GetArticleDeep should return an Article object with Languages included and the entire Person object included (it shouldn't know that the viewmodel needs just the Name of the Person). Also I have so far 3 different viewmodels for an article. For example if someone wants to see the list of articles, then it's unnecessary to get the languages, the body and some other properties, however it might be useful to get the Name of the publisher (which is in the deep). Before "testable" code the controller actions could just contain the linq to entities query and get whichever data they need using lazy loading, Include function, using subqueries, referencing foreign properties (Publisher.Name) ... So there is no unnecessary query to the database and no unnecessary data transferred from the database.
What should be the IService or IRepository interface provide to get the 3-4 different level of Article objects or sometimes list of these objects?
Not sure if you are planning to stick with lazy loading, but if you want a flexible way to integrate eager loading into your repository and service layers first check out this article:
http://blogs.msdn.com/b/alexj/archive/2009/07/25/tip-28-how-to-implement-include-strategies.aspx
He basically gives you a way to build a strongly-typed include strategy like this:
var strategy = new IncludeStrategy<Article>();
strategy.Include(a => a.Author);
Which can then be passed into a general method on your repository or service layers. This way you don't have to have a separate method for each circumstance (i.e. your GetArticleDeep method).
Here is an example repository method using the above include strategy:
public IQueryable<Article> Find(Expression<Func<Article, bool>> criteria, IncludeStrategy<Article> includes)
{
var query = includes.ApplyTo(context.Articles).Where(criteria);
return query;
}

Resources