I am trying to find the best way to generate an enities, this is what I am doing at the moment.
I create an entity trough a mapper and a hydrator like this:
namespace Event\Model\Mapper;
use ZfcBase\Mapper\AbstractDbMapper;
class Event extends AbstractDbMapper
{
protected $tableName = 'events';
public function findEventById($id)
{
$id = (int) $id;
$select = $this->getSelect($this->tableName)
->where(array('event_index' => $id));
$eventEntity = $this->select($select)->current();
if($eventEntity){
//Set Location Object
$locationMapper = $this->getServiceLocator()->get('location_mapper');
$locationEntity = $locationMapper->findlocationById($eventEntity->getLocationIndex());
$eventEntity->setLocationIndex($locationEntity);
//Set User Object
$userMapper = $this->getServiceLocator()->get('user_mapper');
$userEntity = $userMapper->findUserById($eventEntity->getEnteredBy());
$eventEntity->setEnteredBy($userEntity);
//Set Catalog Object
$catalogMapper = $this->getServiceLocator()->get('catalog_mapper');
$catalogEntity = $catalogMapper->findCatalogById($eventEntity->getCatalogIndex());
$eventEntity->setCatalogIndex($catalogEntity);
}
return $eventEntity;
}
}
Now the problem with this approach is that when I call let say the User entity this entity has other entities attach to it so when I generate the Event entity by inserting the User entity my Event entity becomes very large and bulky, I dont want that I just want the first layer of the "gerontology tree".
So I was thinking on creating a EventEntityFactory where I can bind together the child entities of the Event enity, I was planning on doing a factory for this.
Is there a better way of doing this?
Thanks
One approach would be to use Virtual Proxies (with lazy loading):
http://phpmaster.com/intro-to-virtual-proxies-1/
http://phpmaster.com/intro-to-virtual-proxies-2/
Basically you would generate your entity, and replace any related entities with a light weight proxy object. this object would only load the related entity when required via lazy loading.
I've used this approach many times along with the Datamapper design pattern and it works very well.
Related
The code below returns a single record from my database, as-expected. However, it fails to track changes in the UI. I'm binding myObject's properties to various fields using angularjs. Everything initially loads fine, but if I make changes to the object and use breeze's EntityManager.saveChanges(), it doesn't detect than anything has changed. I can create a new entity and save it just fine, but trying to understand how to handle updates. Do I need to detach the entity after I retrieve it, then reattach and save?
Or is this the wrong way to assign a retrieved entity to my javascript (using TypeScript) object?
myObject = data.results[0];
let query = breeze.EntityQuery.from("myTable").where('id', '==', incomingId).expand(['relatedTable']);
dataService.executeQuery(query).then((data) => {
this.myObject = data.results[0];
});
I had to add '.toType("myType")' clause onto the query. I used 'metadataStore.registerEntityTypeCtor' to register my types in the EntityManager, but this step was still necessary for me, which I don't entirely understand.
let query = breeze.EntityQuery.from("myTable").where('id', '==', incomingId).expand(['relatedTable']).toType("myType");
dataService.executeQuery(query).then((data) => {
this.myObject = data.results[0];
});
Edit: I also found that using the EFContextProvider to do my querying improved my results and lessened issues incredibly. In the past, I had only used the Context, and while it worked, my entity types were not understood as well by Breeze on the client side.
readonly EFContextProvider<Context> _contextProvider = new EFContextProvider<Context>();
[HttpGet]
public IQueryable<Dispute> Disputes()
{
return _contextProvider.Context.Disputes;
}
We have controllers that read Entities with certain criteria and return a set of view models containing the data to the view. The view uses a Kendo Grid, but I don't think that makes a particular difference.
In each case, we have a Linq Query that gets the overall collection of entity rows and then a foreach loop that creates a model from each row.
Each entity has certain look ups as follows:
those with a 1:1 relationship, e.g. Assigned to (via a foreign key to a single person)
those with a 1:many relationship e.g. copy parties (to 0:many people - there are not many of these)
counts of other relationships (e.g. the number of linked orders)
any (e.g. whether any history exists)
If we do these in the model creation, the performance is not good as the queries must be run separately for each and every row.
We have also tried using includes to eager load the related entities but once you get more than two, this starts to deteriorate too.
I have seen that compiled queries and LoadProperty may be an option and I am particularly interested in the latter.
It would be great to understand best practice in these situations, so I can direct my investigations.
Thanks,
Chris.
Edit - sample code added. However, I'm looking for best practice.
public JsonResult ReadUsersEvents([DataSourceRequest]DataSourceRequest request, Guid userID)
{
var diaryEventModels = new List<DiaryEventModel>();
var events = UnitOfWork.EventRepository.All().Where(e => e.UserID == userID);
foreach (var eventItem in events)
{
var diaryModel = new DiaryEventModel(eventItem);
diaryEventModels.Add(diaryModel);
}
var result = diaryEventModels.ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet);
}
public DiaryEventModel(Event eventItem) {
// Regular property from Entity examples - no issue here as data retrived simply in original query
ID = eventItem.ID;
Start = eventItem.StartDateTime;
End = eventItem.EndDateTime;
EventDescription = eventItem.Description;
// One to one looked up Property example
eventModel.Creator = eventItem.Location.FullName;
// Calculation example based on 0 to many looked up properties, also use .Any in some cases
// This is a simplified example
eventModel.AttendeeCount = eventItem.EventAttendees.Count();
// 0 to Many looked up properties
EventAttendees = eventItem.EventAttendees.Select(e => new SelectListItem
{
Text = e.Person.FullName,
Value = e.Person.ID.ToString()
}).ToList();
}
I am new to NHibernate. We are using Dapper for retrieval and planning to use NHibernate for CRUD.
I am trying to remove the child object through parent list object in one to many relationship.
This works when I retrieve the object using NHibernate session and remove the item.
var mercedes = Read("chevrolet"); //queries from nhibernate session
var model = mercedes.Models.Where(c => c.Id == 181).Single();
mercedes.Models.Remove(model);
When I manually create the object and attach thecars models, it is unable to remove it.
var mercedes = new Make() { Id = 77, Name = "chevrolet" };//manually created the object
mercedes.Models = GetAllModels(77);//I have it in-memory
var model = mercedes.Models.Where(c => c.Id == 173).Single();
mercedes.Models.Remove(model);
I think I am doing something weird. But I am able to add/update the models using second approach, so why can't i remove it. Any insights please.
When you create a new domain object it isn't attached to the NHibernate session (unless you are creating a new object and call Save, for instance). As such, deleting from the models collection doesn't actually do anything.
Your second example doesn't seem like a particularly good practice but you can recreate an object and attach it to your NHibernate session using Session.Lock (Merge or Update are fairly normal depending on your preferred behavior).
I have a little project where I'm running MVC3.
I use LINQ to fetch data from the database.
I built my project with the same architectural design as the premade examples that come with MVC3.
In such a project, the application is split up and in this topic I want to focus on the Model.cs files. I have one for each controller at the moment, So as an example, I have a HighscoreController.cs and a HighscoreModels.cs. In the model class I define a Service class that has a reference to a datacontext and some methods that use this datacontext to query the database.
Now i ran into the problem that some of these methods are executing the same queries, and therefore I wanted to make a central point of access to the database so I thought I would implement the Repository Pattern, and so I did.
So instead of having a reference to a datacontext in the Service class I now have a reference to the repository as such:
private IRepository _repository;
public HighscoreService()
: this(new Repository())
{ }
public HighscoreService(IRepository repository)
{
_repository = repository;
}
Now the database calls are handled within the repository and the repository is used from the Service class through the _repository reference.
My repository is built like this:
public class Repository : IRepository
{
private MyDataContext _dataContext;
public Repository()
{
_dataContext = new MyDataContext();
}
public Member MemberByName(string memberName)
{
Member member = CompiledQueries.MemberByName(_dataContext, memberName);
return member;
}
}
The problem I face appears when I try to use DataLoadOptions in combination with this repository pattern.
Because when you use dataloadoptions, you must not have made previous queries on the datacontext before a new dataloadoptions is applied to it. And since my repository reuses the datacontext throughout all methods, this does not work out at all.
I have been trying 2 things, one is recreating the datacontext within every methods, by way of the using statement, to make sure that the datacontext is refreshed every time. But then I get problems when I have fetched the result from the repository back into my model and the scope runs out inside the repository pattern, as the using statement ends, which means that the result cannot be used with e.g. .Count() or .ToList() because the datacontext that supplied me the data has been terminated. I also tried another solution where it uses the same datacontext throughout the whole repository, but makes a new instance in each method that uses dataloadoptions. This felt very dirty ;)
So can anyone give me a suggestion on how to use DataLoadOptions with the repository pattern? and avoid the problems I just described. Or should i not use dataloadoptions and choose another way of doing it? The reason i use DataLoadOptions by the way, is that I want to have some data from related tables.
As a little question on the side: In the code example above you can see that I have placed CompiledQueries within a .cs file of its own. Is this a bad design? Are there any guidelines for where to put compiled queries in an MVC application?
Thanks for reading and hope there are some answers for my questions ;) thanks a lot in advance. If you need more information, just ask.
I am by no means an expert on DataLoadOptions, but from your question and what I've read about it, it seems that you need to use it for eager loading. In reference to this:
"Because when you use dataloadoptions, you must not have made previous queries on the datacontext before a new dataloadoptions is applied to it."
.. to me this sounds like a shortcoming or design flaw with DataLoadOptions (I personally use Entity Framework, not LINQ to SQL). While I do think it's a good idea to have a single data context per HTTP request as offered in the first 2 comments by ngm and CrazyCoderz, I don't think this will solve your problem. If you want to reuse a single data context within a single HTTP request, as soon as you execute the first query, it sounds like you will be unable to set the DataLoadOptions on the data context to a new value.
I saw a presentation at vslive vegas where the presenter offered one of the solutions you mentioned, creating a new data context in each repository method. What you would have to do here is call ToList() or ToArray() before terminating the using statement and returning the method result(s).
As you mentioned, this would make objects not pre-loaded into the enumeration inaccessible after the method returns. However, if you already have the query executed and converted to a List, Collection, Array, or some other concrete IEnumerable, you don't need access to the Count() or ToList() methods any longer. Instead, you can use Array.Length or List.Count or Collection.Count properties.
What else is stopping you from creating a new data context in each repository method? Meaning, what do you need the data context for, after executing the repository method, that you can't get because it's been disposed of?
Reply to comments
For your first query, can you do this?
public Member GetSomeRandomMember()
{
Member[] members = null;
using (var context = new MyDataContext())
{
// execute the query to get the whole table
members = context.Members.ToArray();
}
// do not need to query again
var totalRows = members.Length;
var skipThisMany = PerformRandomNumberComputation(totalRows);
return members.Skip(skipThisMany).FirstOrDefault();
}
Granted that might not be optimal if your Members table has a lot of rows. In that case you would want to execute 2 queries -- 1 to count, and a second to select the row. You could achieve that by opening 2 contexts:
public Member GetSomeRandomMember()
{
using (var context1 = new MyDataContext())
var totalRows = context1.Members.Count();
var skipThisMany = PerformRandomNumberComputation(totalRows);
Member member = null;
using (var context2 = new MyDataContext())
member = context2.Members.Skip(skipThisMany).FirstOrDefault();
return member;
}
For the second part of your comment, I'm not sure I get what you are talking about. The fetching of the data and the making changes to it should all come in a single operation with a single context anyways:
public void SaveMember(int id, string email, bool isSuspended)
{
using (var context = new MyDataContext())
{
var member = context.Members.Single(m => m.Id == id);
member.Email = email;
member.IsSuspended = isSuspended;
context.SaveChanges(); // or whatever the linq to sql equivalent is
}
}
If you want to pass the whole entity to the repository method, you should still query it out so that it is attached to the correct context:
public void SaveMember(Member member)
{
var memberDto = member;
using (var context = new MyDataContext())
{
member = context.Members.Single(m => m.Id == memberDto.Id);
member.Email = memberDto.Email;
member.IsSuspended = memberDto.IsSuspended;
context.SaveChanges(); // or whatever the linq to sql equivalent is
}
}
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;
}