I have a RecipeJDO that contains a List<IngredientJDO>. RecipeJDO "owns" the ingredients. This has been working well for me for several weeks. Now I'd like to introduce a new class "GroceryListJDO", that references the ingredients owned by various recipes.
When I try to persist a new GroceryListJDO I get the following:
javax.jdo.JDOException: Duplicate property name: ingredients_id_OWN
NestedThrowables:
org.datanucleus.exceptions.NucleusException: Duplicate property name: ingredients_id_OWN
javax.jdo.JDOException: Duplicate property name: ingredients_id_OWN
Seems like there is an issue of "ownership" of the ingredients between RecipeJDO and GroceryListJDO.
I could probably change GroceryListJDO to merely contain a List<String> that acts as a kind of foreign key to IngredientsJDO, but that kind of defeats the purpose of using ORM- I'd have to manually fetch and attach the ingredients in my DAO.
What is the best way to manage JDO collections that need to "attach" to multiple container JDO classes?
This is with JDO on Google App Engine, FWIW.
Apparently, this is known as an "unowned" relationship, and is not directly supported in GAE. The workaround is what I feared: only one JDO class can own the collection; any other JDOs that reference these objects must persist only Keys, and manage the fetching/saving of the referenced objects manually.
Related
I am working through the ASP.net Web API 2 book (Git Hub)
I am trying to use Fluent NHibernate and Automapper to connect to a database. The book uses a fresh database while my database is pre-existing and not necessarily controlled by good practices.
Before joining tables etc. I would like to just be able to get a list of people and add a new person via the API. The only catch is that I would like to return less properties of the actual table and create a new person with even less than the model used to display a new person. I am having trouble understanding the flow of the automapper.
An example table might be
<pre>Person Entity
-person_id(int)
-person_name(varchar(100))
-person_location(int)
-person_phone(varchar(10))
-person_address(varchar(30))
</pre>
The model I want to use includes a subset of the items in the actual table. For example, maybe:
<pre>Person Model
-person_id(int)
-person_name(varchar(100)
-person_location(int)</pre>
There is also a newPerson model
<pre>NewPerson Model
-Name
-location</pre>
I have an Entity with all the person properties like
public virtual int person_id {get;set;}
but I have a model with the subset properties like
public long person_id {get; set;}
In the automapping configuration file I have a class NewPersonToPersonEntityAutoMapperTypeConfigurator and I have another class PersonEntityToPersonAutoMapperTypeConfigurator
I'm confused about how automapper is working. Should the AutoMapper file NewPersonToPersonEntityAutoMapperTypeConfigurator use something like
Mapper.CreateMap<NewPerson, PersonEntity>
.ForMember(opt => opt.person_id, x => x.Ignore())
...
.ForMember(opt => opt.person_address(varchar(30)))
While
PersonEntityToPersonAutoMapperTypeConfigurator uses something like
Mapper.CreateMap<PersonEntity, PersonModel>
Can anyone show me a good example of a simple scenario like this with automapper and a pre-existing table with extra unused properties or describe what Automapper should be doing or if I am on the right track?
Daniel - I think you're on the right track. Yes, you need an AutoMapper map for each "direction"... i.e. incoming service message to the EF entity, and from the EF entity to the service return message.
Your code to ignore certain properties is fine. You just need to make sure the entity is populated appropriately for the INSERT into the database. For example, the person_id column - is that required to be set? Or is that an auto-incrementing column??
To say it another way... you can certainly use AutoMapper (and our approach in the book) against an existing database. It's still just mapping properties from one type to another type.
Feel free to send some code my way.
I am try to persist an instance (entity) that contains a predefined instances(entities), with JPA and GAE, the relation is oneToOne, as the following:
#Entity class Address{ ... #OneToOne(cascade = CascadeType.ALL)private City city;}
#Entity class City{...}
I created city instance(entity) and persist it, works good, when trying to create Address instance that contains the created city instance(since from UI, it selected from dropdown box), I got the following exception:
javax.persistence.PersistenceException: Detected attempt to establish Address(no-id-yet) as the parent of City(20) but the entity identified by City(20) has already been persisted without a parent. A parent cannot be established or changed once an object has been persisted.
Is there any annotation(s) should be used in order to make this happen?
Thanks in advance
The problem is how DataStore stores keys. Your type of relation is Parent/Child, so for City you will have Adress as a Parent. This mean that you will have composite key with parent as an Address. Your City was already persists so you will not be able to change key (keys can not be changes dynamically after creation. They are immutable).
I do not think that OneToOne reference is suitable for you. Why do you need a separate object? If you really need it - do not try to keep reference integrity. It is very expensive in NoSQL and could cause a lot of problems.
Let's say I'm modeling a website where a web page would be represented by a PageModel, like so:
class PageModel(db.Model):
name = db.StringProperty()
parentPage = db.SelfReferenceProperty()
content = db.TextProperty()
I'd like to be able to pull a list of all my page objects, in order to render menus, etc., but without having to pull in the content for all the items. How would you model this object so that you could pull in the content only when you needed it? Would it require a 1-to-1 reference relationship with a separate 'content' model? And if so, would you make the reference on the page object or on the content object?
You could move the content property into a new model (PageContentModel). I would implement the reference by having the parent of the PageContentModel be the PageModel (using the parent property of db.Model). This allows you to modify both of them in a single transaction (as they are in a single entity group).
One benefit of modeling things with the PageContentModel having a reference to the PageModel (as opposed to the PageModel having a reference to the PageContentModel) is that if you ever need content to be larger than 1MB you can do so by allowing each PageModel to have 1 or more PageContentModel objects and you would just split your content into 1MB chunks and write each chunk to a different PageContentModel instance. To be able to get the content back you would need the PageContentModel objects to have an "order" property associated with them so you can re-build your content in the correct order.
To query for the PageContentModel instances related to a PageModel you would use the ancestor filter like this:
PageContentModel.all().ancestor(page_model_instance)
As suggested by #Nick another way to do this would be to use the files api to write the content to a blob in the blobstore and then link that blob to the PageModel by having a BlobReferenceProperty on the PageModel. I have now had a chance to try this and it is working pretty well (despite it being an experimental feature). This would allow your content to be very large and, under the new pricing model, is actually cheaper than storing your content inside the datastore model.
Updated Feb 7, 2012 to include suggestion from #Nick about the blobstore.
I would like to create a Group model in Google App Engine and then have an attribute where I can create a list of UserReferences. The documentation said:
"A property can have multiple values, represented in the datastore API as a Python list. The list can contain values of any of the value types supported by the datastore."
Would I implement this by creating:
class Group(db.Model):
group_list = db.ListProperty(users.User)
Or might I be better served by simply listing the user entity keys?
http://code.google.com/appengine/docs/python/datastore/entitiesandmodels.html
keys are better placed in ReferenceProperty and their purpose is to create relationships between two kinds.
You can simply create the listproperty and as your list grows keep adding listitems to it.
class Group(db.Model):
group_list = db.ListProperty()
This depends on your use-case. If you already have a User model, to store additional data about your users, then using a db.ListProperty(Key) for User model keys is probably your best option.
I have a table in my database called "Task". Task has the following fields:
- ID
- Description
- AssignedUserID
- TaskTypeID
I am accessing this table through a class that was created automatically after I used an ADO.NET Entity Data Model. I can load and show the fields mentioned above in a DataGrid in my Silverlight application. However, AssignedUserID and TaskTypeID are not very descriptive. So I decided to create a stored procedure that gets the tasks and the user and task type names through their respective lookup tables. This is where the problem lies.
I want to create some custom properties in the automatically generated "Task" class. The custom properties would be named "AssignedUserName" and "TaskType". I then want to make these properties available to my Silverlight client. However, I cannot seem to figure out how to get them exposed to my Silverlight client.
Can someone help?
Thank you
If your EDM is in the same project as the DomainService you can do this:
create a partial class on the Entity type, and add your calculated property in there.
name the file **.shared.cs
it will then be auto-shared with the client/Silverlight code.
Edit:
I was assuming that you could do this calculation in app logic rather than use an sp, which seems more straightforward to me.
If you do use an SP, you'll need to use the Function Import feature in the designer to map the SP to a function in the EDM. This function can then return entities, with properties mapped however you like.
An easier way would be to just use the object model: Have Task.AssignedUser and Task.TaskType objects off of your Task class. Map these to lookup tables in your db. This will work out-of-the box (assuming the Id's are FK's to those lookup tables).
So, a couple options:
use app-logic--properties in a partial class to return the descriptions
use the object model driven by FKs to lookup tables, then just access Task.AssignedUser.Name or Task.TaskType.Description
use a function import to access the SP and map the returned values to entity properties
1 or 2 being the best options IMHO.
Another approach might be to update your EF model to include the lookup tables, add Associations between the tables, add [Include]s in the (auto-gen'd) metadata class and let EF and RIA do it for you. Maybe.