How would you do this (pseudo code): product1.Orders.AddRange(product2.Orders);
However, the function "AddRange" does not exist, so how would you copy all items in the EntityCollection "Orders" from product2 to product1?
Should be simple, but it is not...
The problem is deeper than you think.
Your foreach attempt fails, because when you call product1.Orders.Add, the entity gets removed from product2.Orders, thus rendering the existing enumerator invalid, which causes the exception you see.
So why does entity get removed from produc2? Well, seems quite simple: because Order can only belong to one product at a time. The Entity Framework takes care of data integrity by enforcing rules like this.
If I understand correctly, your aim here is to actually copy the orders from one product to another, am I correct?
If so, then you have to explicitly create a copy of each order inside your foreach loop, and then add that copy to product1.
For some reason that is rather obscure to me, there is no automated way to create a copy of an entity. Therefore, you pretty much have to manually copy all Order's properties, one by one. You can make the code look somewhat more neat by incorporating this logic into the Order class itself - create a method named Clone() that would copy all properties. Be sure, though, not to copy the "owner product reference" property, because your whole point is to give it another owner product, isn't it?
Anyway, do not hesitate to ask more questions if something is unclear. And good luck.
Fyodor
Based on the previous two answers, I came up with the following working solution:
public static void AddRange<T>(this EntityCollection<T> destinationEntityCollection,
EntityCollection<T> sourceEntityCollection) where T : class
{
var array = new T[sourceEntityCollection.Count()];
sourceEntityCollection.CopyTo(array,0);
foreach (var entity in array)
{
destinationEntityCollection.Add(entity);
}
}
Yes, the usual collection related functions are not there.
But,
1. Did you check CopyTo method?
2. Do you find any problem with using the iterator? You know, GetEnumerator, go through the collection and copy the entities?
The above two can solve your problems. But, I'm sure in .NET 3.0+ there would be compact solutions.
My answers are related to .NET 2.0
Related
Imagine you have a method on the server side, in one of your entities Repository.
This method INSERTS or UPDATES Foo entities in the Db.
And you need to name this method.
From the naming convention point of view, can you explain the differences -if there is- between those names:
SaveFoo(Foo foo)
PersistFoo(Foo foo)
CreateFoo(Foo foo)
SaveOrUpdate(Foo foo)
Or what is the naming convention for such methods that only INSERTS or UPDATES to Db?
What's the purpose of the function? To save (or persist, if you like) it, right? You probably don't care whether the function had to insert or update it... that's abstracted away so you don't have to think about it. So just call it Save or Persist, whichever you prefer. That's my two cents.
If you work in a team, you should first try to find out if there is a convention there, as it's usually more important to be consistent than to find the absolute best name for something.
Using Save or Persist would work, as they don't imply anything about the previous state.
Using Create would imply that the item doesn't already exists, i.e. an insert.
Using SaveOrUpdate could be somewhat confusing, as Update implies that the item already exists, but Save doesn't imply anything about the state, so they overlap.
Perhaps InsertOrUpdate would be an alternative, or CreateOrUpdate. Either would work as Insert and Create implies that the item doesn't exist yet, and Update implies that it does exist, so they don't overlap. They are also more precise than Save or Persist, as the names specifically say that they handle both insert and update.
Looking at .NET Framework, ConcurrentDictionary<,> uses .AddOrUpdate()
I'm using a homebrewed repository pattern (!) together with PetaPoco in my latest project. And when coding some data retrieval routines my brain suddenly made a jump.
Currently i have Repo.GetMyObjects that returns an IList<MyObject> from the db, and a Repo.GetMyObject that returns a MyObject.
Is this the correct way to go ahead? Or should I have my Repo.GetMyObjects return an IEnumerable<MyObject> and then use Repo.GetMyObjects().SingleOrDefault( q => q.ID == MyWantedObjectID) in my controller to get a single object?
To go even further than Ankur's answer: the way you are doing is actually more correct, because having to add SingleOrDefault() calls would seem to be something the repository should be doing for you.
Let your Repo.GetMyObject bet there and make it do what you have described. So that in future if required you can change the implementation and all the callers won't need any change.
It would be stupid to retrieve a whole collection of MyObject instances, if you only need one. Consider the performance-cost that this gives you, if you have thousands of instances in your database.
So, you'll need a GetMyObject method in your repository, which retrieves the only object you're interested in.
I'm new to NHibernate, but have managed to get it all running fine for my latest project. But now I've reached the inevitable performance problem where I need to get beyond the abstraction to fix it.
I've created a nunit test to isolate the method that takes a long time. But first a quick overview of my domain model is probably a good idea:
I have a 'PmqccForm' which is an object that has a 'Project' object, which contains Name, Number etc and it also has a 'Questions' object, which is a class that itself contains properties for various different 'Question' objects. There is a JobVelocityQuestion object which itself has an answer and some other properties, and a whole bunch of similar Question objects.
This is what I'm talking about with my PmqccForm having a Questions object
This is the questions part of the model:
The key point is that I want to be able to type
form.Questions.JobVelocityQuestion
as there is always exactly 1 JobVelocityQuestion for each PmqccForm, its the same for all the other questions. These are C# properties on the Questions object which is just a holding place for them.
Now, the method that is causing me issues is this:
public IEnumerable<PmqccForm> GetPmqccFormsByUser(StaffMember staffMember)
{
ISession session = NHibernateSessionManager.Instance.GetSession();
ICriteria criteria = session.CreateCriteria(typeof(PmqccForm));
criteria.CreateAlias("Project", "Project");
criteria.Add(Expression.Eq("Project.ProjectLeader", staffMember));
criteria.Add(Expression.Eq("Project.IsArchived", false));
return criteria.List<PmqccForm>();
}
A look in my console from the Nunit test which just runs this method shows that there is nearly 2000 sql queries being processsed!
http://rodhowarth.com/otherstorage/queries.txt is the console log.
The thing is, at this stage I just want the form object, the actual questions can be accessed on a need to know basis. I thought that NHibernate was meant to be able to do this?
Here is my mapping file:
http://rodhowarth.com/otherstorage/hibernatemapping.txt
Can anyone hint me as to what I'm missing? or a way to optimize what I'm doing in relation to NHibernate?
What if I made the questions a collection, and then made the properties loop through this collection and return the correct one. Would this be better optimization from nhibernates point of view?
Just try to add fetch="subselect" to the mapping file for Questions component and see if this solves the issue with multiple selects to that table - you should now see one 2nd select instead of hundreds separate queries, e.g.
<component name="Questions" insert="true" update="true" class="PmqccDomain.DomainObjects.Questions" fetch="subselect">
See for more info - Improving performance
I'm considering using PostSharp for entity-to-DTO and DTO-to-entity mapper. To do that task manualy for about a 100 entities would be a maintenence nightmare. I've looked at AutoMapper on codeplex, but i think the overhead might be a serious problem in my case, besides i feel that PostSharp could give me some extra control over the mapping convention. If anyone can share any experiences with this king of problems, that would be great.
The direction i'm think in is something like this (please somebody tell me if this is not possible):
The aspect that i am planing to stick to a class would fill the next two methods with content:
EntityType EntityToDTO(DTOType DTO) {}
DTOType DTOToEntity(EntityType Entity) {}
The first method would return entity based on DTO, the second one would do the oposite. Inside the aspect i'm planing to loop through each property, create new target and asign the value of a property to the counterpart from target object. Is this possible to do at compiletime witout any runtime overhead?
If your DTOs field names match your entity field names, then I'd use Duck Typing
http://www.deftflux.net/blog/page/Duck-Typing-Project.aspx
http://haacked.com/archive/2007/08/19/why-duck-typing-matters-to-c-developers.aspx
Your code would work like this
UserDTO user = DuckTyping.Cast<UserDTO>(userEntity);
Basically, the duck typing library will be mapping over the fields by matching the names. They use dynamically generated IL to archive this.
If that has the potential of being too slow, I'd probably try to get CodeSmith to generate the methods for me.
If it helps, there is a project called PostSharp4ET that basically implements support for POCO objects to Entity Framework 1. See http://www.codeplex.com/efcontrib.
Note that PostSharp is not very good at generating new code. It is good at mixing new code with existing one. If you need to generate code, I would recommend writing a C# code generator based on reflection, and compile the resulting code. Or use a tool like CodeSmith, as mentioned previously.
I'm trying to use ASP.NET's Repeater objects to loop over properties of an object.
For example... I have an ObjectDataSource to grab object "Program" by ID...
Program has properties such as Program.Stakeholders and Program.Outcomes which are Lists of "Stakeholder" and "Outcome" objects.
Now... what I'd really like to do is use the Repeaters to target these Properties and loop over the lists they contain. However, as far as I know I'd have to set up a separate data source for each one, tied to an individual method to retrieve each list.
Can anyone provide a better way to use these Repeater objects, or point me at some resources which would help? If this doesn't make sense I can try to clarify it more.
Using the built-in ObjectDataSource mapping up a separate datasource for each item is probably the only straightforward way (and the only way that's easy enough to be worth the effort...).
Is it a requirement that you use the ObjectDataSource, or can you choose a different way to get the data from the storage? I would recommend either using Entity Framework (which imho rocks) or creating your own custom types to which you get the data with a custom designed DAL (which is a lot more work than using EF, but if you're, like some, concerned that EF is still in infancy this might be your option).
In either case, you'll end up with a C# class called Program, which has properties of type IEnumerable<Stakeholder> and IEnumerable<Outcome> called Stakeholders and Outcomes respectively. You can then use these as datasources for the item repeaters and set them in the ItemDataBound event of the ProgramRepeater, maybe something like this:
protected void ProgramRepeater_ItemDataBound(object sender, ItemDataBoundEvent e) {
Program dataItem = (Program)e.DataItem;
Repeater stakeholderRptr = (Repeater)e.Item.FindControl("ProgramRepeater");
Repeater outecomeRptr = (Repeater)e.Item.FindControl("OutcomeRepeater");
stakeholderRptr.DataSource = dataItem.Stakeholders;
stakeholderRptr.DataBind();
outecomeRptr.DataSource = dataItem.Outcomes;
outecomeRptr.DataBind();
}
This is assuming that you're using ASP.Net WebForms, of course. In ASP.Net MVC it is even easier - you just send the Program object to the View as the Model object, and loop through its Stakeholders and Outcomes in a couple of nested for loops directly on the View.
Note: All code is provided as is, and I do not guarantee that it will run as expected or even compile. It is just to give you an idea of what to make your code do - not necessarily the exact code you need to solve your problem.