I'm recently concerned in the problems we have with Entity Framework and we may need to find a replacement. According to ORMBattle, the best candidate is DataObjects.Net, the result of my initial investigations are very promising, except one feature that we need in our structure:
Consider two classes: Order and Customer, in class "Order" I have a "Customer" navigation property (and probably an "Orders" navigation property in the Customer class). I also need a property CustomerID in class Order.
this is totally possible in lowly EF4.
How can I achieve this goal?
you can add non-persistent property with special getter that does the job:
public long CustomerId
{
get
{
return GetReferenceKey(TypeInfo.Fields["Customer"]).Value.GetValue<long>(0);
}
}
The setter can be added in the same manner.
Hope that helps.
P.S.
This is a copy of the original answer that can be found on the official DataObjects.Net support site.
Related
I have a two aggregate roots in my domain, and therefore two repositories. We'll call them BookRepository, and AuthorRepository, for the sake of example.
I'm designing an MVC application, and one page has to display a table containing a list of authors, with each row showing the author's personal details. At the end of each row is a small button that can be clicked to expand the row and show a child table detailing the author's published books.
When the page loads, some ajax is executed to retrieve the Author details from an API controller and display the data in the table. Each property in an Author object maps almost directly to a column, with one exception, and this is where I'm having my problem. I want the button at the end of each row to be disabled, if and only if the author has no published books. This means that a boolean has to returned with each Author record, indicating if they have any published books.
My book repository has a couple of methods like this:
public IEnumerable<Book> GetBooksForAuthor(int authorId);
public bool AnyBooksForAuthor(int authorId);
and my Book class has a property called AuthorId, so I can retrieve a book's author by calling
authorRepository.GetById(book.AuthorId);
My problem is that in order to create a row for my aforementioned table, I need to create it like this:
IEnumerable<Author> authors = authorRepository.GetAll();
foreach (Author author in authors)
{
yield return new AuthorTableRow
{
Name = author.Name,
Age = author.Age,
Location = author.PlaceOfResidence.Name,
HasBooks = this.bookRepository.AnyBooksForAuthor(author.Id)
};
}
The above code seems correct, but there's a fairly heft performance penalty in calling this.bookRepository.AnyBooksForAuthor(author.Id) for every single author, because it performs a database call each time.
Ideally, I suppose I would want an AuthorTableRowRepository which could perform something like the following:
public IEnumerable<AuthorTableRow> GetAll()
{
return from a in this.dbContext.Authors
select new AuthorTableRow
{
Name = a.Name,
Age = a.Age,
Location a.PlaceOfResidence.Name
HasBooks = a.Books.Any()
});
}
I'm hesitant to put this in place for these reasons :
AuthorTableRowRepository is a repository of AuthorTableRows, but AuthorTable row is not a domain object, nor an aggregate root, and therefore should not have its own repository.
As Author and Book are both aggregate roots, I removed the "Books" property from the Author entity, because I wanted the only way to retrieve books to be via the BookRepository. This makes HasBooks = a.Books.Any() impossible. I am unsure whether I am imposing my own misguided best practice here though. It seems wrong to obtain Books by obtaining an Author via the AuthorRepository and then going through its Books property, and vice versa in obtaining an Author via a property on a Book object. Crossing aggregate root boundaries would be the way I'd term it, I suppose?
How would other people solve this? Are my concerns unfounded? I am mostly concerned about the (what should be a) performance hit in the first method, but I want to adhere to best practice with the Repository pattern and DDD.
I would stick to the first approach, but try to optimize things in the bookrepository method. For instance, you can load this information all in one time, and use in-memory lookup to speed this up. Like this you would need 2 queries, and not 1 for each author.
The way I solved this in the end was to create an Entity from a view in the database. I named the entity 'AuthorSummary', and made an AuthorSummaryRepository that didn't contain any Add() methods, just retrieval methods.
I have an Open JPA entity and it successfully connects a many-to-many relationship. Right now I successfully get the entire table, but I really only want the ID's from that tables. I plan on calling the database later to reconstruct the entities that I need (according to the flow of my program).
I need only the ID's (or one column from that table).
1) Should I try and restrict this in my entity beans, or in the stateless session beans that I will be using to call the entity beans
2) If I try and do this using JPA, how can I specify that I only get back the ID's from the table, instead of the whole table? So far looking online, I don't see a way that you can do this. So I am guessing there is no way to do this.
3) If I simply just manipulate the return values, should I create a separate class that I will be returning to the user that will return only the required id list to the user?
I could be completely wrong here, but from the looks of it, I don't think there is a simple way to do this using JPA and I will have to return a custom object instead of the entity bean to the user (this custom object would only hold the id's as opposed to the whole table as it currently does)
Any thoughts... I don't think this is really relevant, but people are always asking for code, so here you go...
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name="QUICK_LAUNCH_DISTLIST",
joinColumns=#JoinColumn(name="QUICK_LAUNCH_ID"),
inverseJoinColumns=#JoinColumn(name="LIST_ID"))
private List<DistributionList> distributionlistList;
Currently how I get the entire collection of records. Remember I only want the id...
try
{
//int daSize = 0;
//System.out.println("Testing 1.2..3...! ");
qlList = emf.createNamedQuery("getQuickLaunch").getResultList();
}
This is how I call the Entity beans. I am thinking this is where I will have to programatically go through and create a custom object similar to the entity bean (but it just has the ID's and not the whole table, and attempt to put the id's in there somewhere.
What are your thoughts?
Thanks
I believe I just figured out the best solution to this problem.
This link would be the answer:
my other stack overflow answer post
But for the sake of those too lazy to click on the link I essentially used the #ElementCollection attribute...
#ElementCollection(fetch=FetchType.EAGER)
#CollectionTable(name="QUICK_LAUNCH_DISTLIST",joinColumns=#JoinColumn(name="QUICK_LAUNCH_ID"))
#Column(name="LIST_ID")
private List<Long> distListIDs;
That did it.
Sounds like you want something like this in your quickLaunch class:
#Transient
public List<Integer> getDistributionListIds () {
List<Integer> distributionListIds = new LinkedList<Integer>();
List<DistributionList> distributionlistList = getDistributionlistList();
if (distributionlistList != null) {
for (DistributionList distributionList : distributionlistList)
distributionListIds.add(distributionList.getId());
}
return distributionListIds;
}
I had to guess a little at the names of your getters/setters and the type of DistributionList's ID. But basically, JPA is already nicely handling all of the relationships for you, so just take the values you want from the related objects.
I'm pretty new to the Entity framework and I'm modelling this simple structure:
With this model what I have is a Users class with a property UsersGroups (a collection of UserGroups objects).
I would like to have a Users class with a property like Groups with type Tuple or something like this (a new PriorizedGroup class, etc) that is much more related with the bussines.
Is this possible with the Entity framework?
Thanks in advance.
EDIT: If I were modeling the bussines objects I would create a User class with a Groups property that contained all the groups the user pertains with an extra property to store its priority (with a tuple, with an inherited class, as you wish). The thing is that I feel that the objects created by the Entity framework resemble the SQL structure, not the business structure.
Not directly. EF can map the relation only in the way you see it at the moment but you can add your custom behavior to your partial part of the entity. The simple way is something like
public partial class Users
{
public IEnumerable<PrioritizedGroup> Groups
{
get
{
return UserGroups.Select(ug => new PrioritizedGroup
{
Priority = ug.Priority,
Id = ug.Group.Id,
Name = ug.Group.Name,
Description = ug.Group.Description
})
.OrderBy(g => g.Priority);
}
}
}
To make this happen directly in EF you need some advanced mapping technique which will require you to modify EDMX source code directly (either DefiningQuery or QueryView) and it will make the entity read only (you will need stored procedures for modification).
To make the collection exposed on Users updatable you would probably need to use ObservableCollection and transfer all modifications triggered by ObservableCollection back to original UserGroups collection. Once you have something like that implemented you can hide original collection.
I have a table structure like the following:
Companies Addresses
********* *********
ID ID
AddressID ...
BillingAddressID ...
AddressID and BillingAddressID are foreign keys which are present in the Addresses table. When I generate my model based on this table instead of getting what I would expect to get (the AddressID, BillingAddressID) in the company class. I get the following:
public Addresses Addresses { .. }
public global::System.Data.Objects.DataClasses.EntityReference<Addresses> AddressesReference { .. }
public Addresses Addresses1 { .. }
public global::System.Data.Objects.DataClasses.EntityReference<Addresses> Addresses1Reference { .. }
It seems to be replacing BillingAddress with Addresses1 (not quite sure why that's happening). Also this seems to be common wherever I have a foreign key i.e. instead of the ID I get Table then the TableReference.
I think I can see whats happening i.e. instead of giving me the ID alone, it will be doing a lookup and finding the actual record the ID refers to. However, I am not quite sure what the TableReference field is for....
Can explain this a little better for me?
Thanks in advance.
Relationships are represented as objects in Entity Framework, in the same manner as entities. Even if you are not going to work a lot directly on them, relationship object are first class citizens in EF. EF kreates ObjectStateEntry objects for tracking changes on relationships, just like it does it for entities.
That is why there are two references. First one, AddressesReference is a reference to the relationship object, not the exact entity, and second one Addresses is actual entity.
Peter Chan (link), and Julia Lerman in her book Programming Entity Framework, 1st Edition, say that understanding how relationship works in EF is very important. Also they mention that this is first thing that is confusing developer when they start using EF.
The foreign keys are replaced by a reference to the entity (collection) the foreign key points to.
So to add an address to a company you would do something like:
Address a = new Address();
// ... set variables for address here
currentCompany.Addresses = a;
// or, the other way round (for collections)
a.Companies.Add(currentCompany);
EF uses the table names as the reference point when it builds the model and this is why you see "Addresses" and Addresses1". You can open up the entity model in the GUI format and click on each of the associations. These can be renamed to whatever you like, just click on the reference, view the mapping, ensure it is the one that maps "BillingAddressID" to "BillingAddressID" and rename that reference to "BillingAddress".
Note the current "Addresses" reference may be the one mapping the "BillingAddressID" so you have to check both references.
It would probably be best to change the mapping for "AddressID" to be "Address" instead of "Addresses" if it is a one to one mapping as well.
I have 2 entities: User and Company, with a FK from the User to the Company.
I'm trying to remove the association and leave the user entity with a scalar property "CompanyId", but still have the "Company" entity in the model (mainly to increase performance, I don't need to full entity attached to it).
I'm able to achieve that only by removing the association and then go to the edmx (xml) file and remove the leftovers manually, BUT...
After I regenerate the model (following additional changes in the schema etc.), I'm getting the "Company" association once again on the "User" object (along with the "CompanyId" property), which of course causes errors of mappings, since I'm having 2 mappings to the same CompanyId field in the database. Going once again to the xml to fix it is not something I'd like to do...
Is there a way around this? -Taking the "Company" table out to another model is not possible.
Thanks,
Nir.
I think I found the answer.
I can leave the entity association without the scalar property, and set it to a private getter. Then, add to the partial class the following:
public int CompanyId
{
get
{
return
(int)CompanyReference.EntityKey.EntityKeyValues.First(c => c.Key == "Id").Value;
}
}
That way I don't need to go to the database to fetch the company association along with the user, but I still have the value.
Nir.