I have a Curriculum entity which is as follows:
#Entity
public class Curriculum {
#ManyToMany
private Set<Language> languages;
...
I am trying to persist a Curriculum instance but the constraint is that the Language instances are already in database.
How can I make sure that when a call to persist is made, a line is inserted into the curriculum table, the curriculum_languages mapping table but not into the language table as it is a reference table which is already populated?
edit 1:
-Here is the error I get if I don't specify the Cascade.ALL attribute:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.bignibou.domain.Language
-If I do specify the Cascade.ALL, new lines with new IDs are insterted into the language table which is obviously not what I want...
edit 2: Note that I use Spring Data JPA in order to persist my instances and the data coming from the browser is a JSON object as follows:
{"curriculum":{"languages":[{"id":46,"description":"Français"},{"id":30,"description":"Chinois"}],"firstName":"Julianito","dateOfBirth":"1975-01-06","telephoneNumber":"0608965874","workExperienceInYears":3,"maxNumberChildren":1,"drivingLicense":true}}
Probably the most simplest way to achieve it is to load the needed languages from the DB and assign them to the curriculum just before the persist operation.
The logic behind this is the following:
When a language object comes into your application and is deserialized from JSON, it has an ID field already assigned to it.
When you try to persist the curriculum (with languages deserialized from JSON) JPA gets confused about those IDs, cause on the one hand it 'should' know about these objects (IDs are set), but on the other hand active JPA session does not know anything about them (they came from outer world of JSON)
So fetching languages by ID tells JPA who's who.
What should happen, when an inexistent Language comes with a Curriculum instance? Should the Language instance simply be ignored or should an Exception be thrown?
If an exception should be thrown, just wrap the code that persists the entity in a try-catch block and throw your own Exception. If the language should simply be ignored, just remove it from the List<Language> before persisting, e.g if Language's ID is null.
I forgot to mention that I use optimistic locking. Including the version field in JSon sorted the issue:
"languages":[{"id":46,"description":"Français","version":0}],...
It would be great if anyone would kindly provide an explanation to this though...
edit: version field:
#Version
#Column(name = "version")
private Integer Curriculum.version;
Related
I Have Create a DB in that I am Having Multiple tables having Relationship between them.
When a try to get data from my WEb app i get this error
"'Self referencing loop detected with type 'System.Data.Entity.DynamicProxies.PrescriptionMaster_2C4C63F6E22DFF8E29DCAC8D06EBAE038831B58747056064834E80E41B5C4E4A'. Path '[0].Patient.PrescriptionMasters"
I coudn't get why i am getting this error, and when i remove the relationships between tables i get proper data From it.
I have Tried other solutions like adding
"config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
= Newtonsoft.Json.ReferenceLoopHandling.Ignore; "
in Webconfig.cs but nothing has worked for me.
Please help me, what should I do ?
The only proper way to prevent this from happening is by not sending Entity Framework objects (which may contain such loops) into the JSON Serializer (which is not too good at knowing when to stop serializing).
Instead, create ViewModels that mimic the parts of the EF Objects that your Front End actually needs, then fill those ViewModels using the EF Objects.
A quick-and-dirty way is to just use anonymous objects, for example:
return new
{
Product = new
{
Id = EF_Product.Id,
Name = EF_Product.Name
}
};
A good rule-of-thumb is to only assign simple properties (number, bool, string, datetime) from the EF Objects to the ViewModel items. As soon as you encounter an EF Object property that is yet another EF Object (or a collection of EF Objects), then you need to translate those as well to 'simple' objects that are not linked to EF.
On the other end of the spectrum there are libraries such as AutoMapper. If you decide that you need actual ViewModel classes, then AutoMapper will help mapping the EF Objects to those ViewModels in a very structured way.
Just add this to the Application_Start in Global.asax:
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
It will ignore the reference pointing back to the object.
I'm trying to save a breezejs entity which has a collection of entities within it, a selection of 'choices' if you will.
something crudely like
public class Form{
public class Choice{
public string Name {get;set;}
public bool Selected {get;set;}
}
[Key]
public Guid Id{get;set;}
public ICollection<Choice> Choices{get;set;}
}
When breezejs saves the changes to the entities it batches them out to respective odata controllers, one for "Form" and one for "Choice". This would be fine, but I want/need to make the change within a transaction on the server - so ideally I would be able to get a Form model in the Form odata controller which has a collection of Choices populated within it. Then I can make my changes within a single transaction scope.
I spent a few hours digging, but I can't find a way to ask breezejs to 'embed' the collection of 'Choices' within the 'Form' to get a single Post with a fully populated 'Form' model.
Any suggestions?
Thank you!
The current server side OData controllers from MS don't really support transactions involving multiple entity type saves. ( This is a known MS issue, but they have been very slow to address it. )
However, breeze's standard WebApi controller does handle transactions involving multiple entity type saves. And providing that you are using EF, the transition between the two is relatively simple.
See:
http://www.getbreezenow.com/documentation/odata-vs-webapi and
http://www.getbreezenow.com/documentation/aspnet-web-api
I have this problem:
The Vehicle type derives from the EntityObject type which has the property "ID".
I think i get why L2S can't translate this into SQL- it does not know that the WHERE clause should include WHERE VehicleId == value. VehicleId btw is the PK on the table, whereas the property in the object model, as above, is "ID".
Can I even win on this with an Expression tree? Because it seems easy enough to create an Expression to pass to the SingleOrDefault method but will L2S still fail to translate it?
I'm trying to be DDD friendly so I don't want to decorate my domain model objects with ColumnAttributes etc. I am happy however to customize my L2S dbml file and add Expression helpers/whatever in my "data layer" in the hope of keeping this ORM-business far from my domain model.
Update:
I'm not using the object initialization syntax in my select statement. Like this:
private IQueryable<Vehicle> Vehicles()
{
return from vehicle in _dc
select new Vehicle() { ID = vehicle.VehicleId };
}
I'm actually using a constructor and from what I've read this will cause the above problem. This is what I'm doing:
private IQueryable<Vehicle> Vehicles()
{
return from vehicle in _dc
select new Vehicle(vehicle.VehicleId);
}
I understand that L2S can't translate the expression tree from the screen grab above because it does not know the mappings which it would usually infer from the object initialization syntax. How can I get around this? Do I need to build a Expression with the attribute bindings?
I have decided that this is not possible from further experience.
L2S simply can not create the correct WHERE clause when a parameterized ctor is used in the mapping projection. It's the initializer syntax in conventional L2S mapping projections which gives L2S the context it needs.
Short answer - use NHibernate.
Short answer: Don't.
I once tried to apply the IQueryable<.IEntity> to Linq2Sql. I got burned bad.
As you said. L2S (and EF too in this regard) doesn't know that ID is mapped to the column VehicleId. You could get around this by refactoring your Vehicle.ID to Vehicle.VehicleID. (Yes, they work if they are the same name). However I still don't recommend it.
Use L2S with the object it provided. Masking an extra layer over it while working with IQueryable ... is bad IMO (from my experience).
Otherway is to do .ToList() after you have done the select statement. This loads all the vehicles into your memory. Then you do the .Where statment against Linq 2 Object collections. Ofcourse this won't be as effecient as L2S handles all of the query and causes larger memory usage.
Long story short. Don't use Sql IQueryable with any object other than the ones it was originally designed for. It just doesn't work (well).
Is it possible to use the guid.comb strategy for identity generation with Mysql Db using Nhibernate?
When I use it as
mapping.Id(x => x.Id)
.Column("row_guid")
.CustomType(typeof(string))
.GeneratedBy.GuidComb()
.Length(36);
I end up with a
---->
System.InvalidOperationException :
Identity type must be Guid
Is there a way to overcome this obstacle in the MySql scenario?
Edit:
I don’t have a choice between guid and int. This is a port of a legacy db from MSSql
This is common problem especially when porting MSSql applications to MySql.
As David said,implement a simple CustomIdGenerator which is a wrapper over GuidCombGenerator that gives you the Guid as a string.
using NHibernate.Engine;
using NHibernate.Id;
namespace NHibernateMaps
{
public class GuidStringGenerator : IIdentifierGenerator
{
public object Generate(ISessionImplementor session, object obj)
{
return new GuidCombGenerator().Generate(session, obj).ToString();
}
}
}
And in the mapping specify it as
mapping.Id(x => x.Id)
.Column("row_id")
.CustomType(typeof(string))
.GeneratedBy.Custom(typeof(GuidStringGenerator))
.Length(36);
I'm not convinced of the wisdom of using an unsupported data type for your primary key, but if you really do need to do this then you could try writing an NHibernate user type that exposes its property as a Guid but persists to the database as a string. The problem in this case seems to be that the property itself is defined as a data type other than System.Guid, which the guid.comb strategy expects.
I can't guarantee that it still won't error, but it's the only way you'll get it to work if it is possible. If you're new to NHibernate user types, there is an abstract base class that takes care of some of the drudge work for you here, with an example implementation class. You should be able to follow this example.
Just can use System.Guid as the type of the property.
O/RM is about mapping, so even though your database doesn't support a given type natively, you can still use this in your domain model. The underlying type of your column should be BINARY(16), for MySQL compatibility.
I seem to have gotten myself into a bit of a confusion of this whole DDD\LinqToSql business. I am building a system using POCOS and linq to sql and I have repositories for the aggregate roots.
So, for example if you had the classes Order->OrderLine you have a repository for Order but not OrderLine as Order is the root of the aggregate. The repository has the delete method for deleting the Order, but how do you delete OrderLines?
You would have thought you had a method on Order called RemoveOrderLine which removed the line from the OrderLines collection but it also needs to delete the OrderLine from the underlying l2s table. As there isnt a repository for OrderLine how are you supposed to do it?
Perhaps have specialized public repostories for querying the roots and internal generic repositories that the domain objects actually use to delete stuff within the aggregates?
public class OrderRepository : Repository<Order> {
public Order GetOrderByWhatever();
}
public class Order {
public List<OrderLines> Lines {get; set;} //Will return a readonly list
public RemoveLine(OrderLine line) {
Lines.Remove(line);
//************* NOW WHAT? *************//
//(new Repository<OrderLine>(uow)).Delete(line) Perhaps??
// But now we have to pass in the UOW and object is not persistent ignorant. AAGH!
}
}
I would love to know what other people have done as I cant be the only one struggling with this.... I hope.... Thanks
You call the RemoveOrderLine on the Order which call the related logic. This does not include doing changes on the persisted version of it.
Later on you call a Save/Update method on the repository, that receives the modified order. The specific challenge becomes in knowing what has changed in the domain object, which there are several options (I am sure there are more than the ones I list):
Have the domain object keep track of the changes, which would include keeping track that x needs to be deleted from the order lines. Something similar to the entity tracking might be factored out as well.
Load the persisted version. Have code in the repository that recognizes the differences between the persisted version and the in-memory version, and run the changes.
Load the persisted version. Have code in the root aggregate, that gets you the differences given an original root aggregate.
First, you should be exposing Interfaces to obtain references to your Aggregate Root (i.e. Order()). Use the Factory pattern to new-up a new instance of the Aggregate Root (i.e. Order()).
With that said, the methods on your Aggregate Root contros access to its related objects - not itself. Also, never expose a complex types as public on the aggregate roots (i.e. the Lines() IList collection you stated in the example). This violates the law of decremeter (sp ck), that says you cannot "Dot Walk" your way to methods, such as Order.Lines.Add().
And also, you violate the rule that allows the client to access a reference to an internal object on an Aggregate Root. Aggregate roots can return a reference of an internal object. As long as, the external client is not allowed to hold a reference to that object. I.e., your "OrderLine" you pass into the RemoveLine(). You cannot allow the external client to control the internal state of your model (i.e. Order() and its OrderLines()). Therefore, you should expect the OrderLine to be a new instance to act upon accordingly.
public interface IOrderRepository
{
Order GetOrderByWhatever();
}
internal interface IOrderLineRepository
{
OrderLines GetOrderLines();
void RemoveOrderLine(OrderLine line);
}
public class Order
{
private IOrderRepository orderRepository;
private IOrderLineRepository orderLineRepository;
internal Order()
{
// constructors should be not be exposed in your model.
// Use the Factory method to construct your complex Aggregate
// Roots. And/or use a container factory, like Castle Windsor
orderRepository =
ComponentFactory.GetInstanceOf<IOrderRepository>();
orderLineRepository =
ComponentFactory.GetInstanceOf<IOrderLineRepository>();
}
// you are allowed to expose this Lines property within your domain.
internal IList<OrderLines> Lines { get; set; }
public RemoveOrderLine(OrderLine line)
{
if (this.Lines.Exists(line))
{
orderLineRepository.RemoveOrderLine(line);
}
}
}
Don't forget your factory for creating new instances of the Order():
public class OrderFactory
{
public Order CreateComponent(Type type)
{
// Create your new Order.Lines() here, if need be.
// Then, create an instance of your Order() type.
}
}
Your external client does have the right to access the IOrderLinesRepository directly, via the interface to obtain a reference of a value object within your Aggregate Root. But, I try to block that by forcing my references all off of the Aggregate Root's methods. So, you could mark the IOrderLineRepository above as internal so it is not exposed.
I actually group all of my Aggregate Root creations into multiple Factories. I did not like the approach of, "Some aggregate roots will have factories for complex types, others will not". Much easier to have the same logic followed throughout the domain modeling. "Oh, so Sales() is an aggregate root like Order(). There must be a factory for it too."
One final note is that if have a combination, i.e. SalesOrder(), that uses two models of Sales() and Order(), you would use a Service to create and act on that instance of SalesOrder() as neither the Sales() or Order() Aggregate Roots, nor their repositories or factories, own control over the SalesOrder() entity.
I highly, highly recommend this free book by Abel Avram and Floyd Marinescu on Domain Drive Design (DDD) as it directly answers your questions, in a shrot 100 page large print. Along with how to more decouple your domain entities into modules and such.
Edit: added more code
After struggling with this exact issue, I've found the solution. After looking at what the designer generates with l2sl, I realized that the solution is in the two-way associations between order and orderline. An order has many orderlines and an orderline has a single order. The solution is to use two way associations and a mapping attribute called DeleteOnNull(which you can google for complete info). The final thing I was missing was that your entity class needs to register for Add and Remove events from the l2s entityset. In these handlers, you have to set the Order association on the order line to be null. You can see an example of this if you look at some code that the l2s designer generates.
I know this is a frustrating one, but after days of struggling with it, I've got it working.
As a follow up....
I have switched to using nhibernate (rather than link to sql) but in effect you dont need the repos for the OrderLine. If you just remove the OrderLine from the collection in Order it will just delete the OrderLine from the database (assuming you have done your mapping correctly).
As I am swapping out with in-memory repositories, if you want to search for a particular order line (without knowing the order parent) you can write a linq to nhibernate query that links order to orderline where orderlineid = the value. That way it works when querying from the db and from in memory. Well there you go...