How to get a copy of child entity and save it to another parent using DataNucleus and JDO API? - jdo

I have a bidirectional 1 to many relation between SelfEmployed and IncomeExpense classes. Suppose I have two different persistent instances of SelfEmployed. I need to copy of some SelfExpense object from one parent and add them to another.
To copy object I just use default constructor to create instance, and then assign only three primitive values, and sets selfEmployed=null instance and id=null.
BUT, when I do the following secondSelfEmployed.getIncomeExpenses().add(incomeExpenseCopy);
Somehow it finds the origin instance of incomeExpense, and sets the rest fields like id and selfEmployed. Thus, when the transaction commits it throws the exception, that I try to add incomeExpense, that already has its parent object selfEmployed
org.datanucleus.exceptions.NucleusUserException: Management of relations : Object "SelfEmployed#6d651cc" has a bidirectional field "incomeExpenses" and the object"IncomeExpense#60942b95" was added to this field, but this field has had its owner set to "SelfEmployed#1fb974bc"!
import java.util.HashSet;
import java.util.Set;
public class SelfEmployed {
protected Set<IncomeExpense> incomeExpenses = new HashSet<IncomeExpense>();
// some primitive fields
public Set<IncomeExpense> getIncomeExpenses(){
return incomeExpenses;
}
// standard getters and setters
}
and
public class IncomeExpense {
protected int year;
protected Double annualGrossTurnover;
protected Double annualExpenses;
protected SelfEmployed selfEmployed;
// standard getters and setters
public void setSelfEmployed(SelfEmployed selfEmployed) {
this.selfEmployed = selfEmployed;
}
public SelfEmployed getSelfEmployed() {
return selfEmployed;
}
}
The following logic is performed within transaction.
The problem is here
for (IncomeExpense ie: selfEmployed1.getIncomeExpenses()){
IncomeExpense copy = new IncomeExpense();
copy.setYear(ie.getYear());
copy.setAnnualGrossTurnover(ie.getAnnualGrossTurnover());
copy.setAnnualExpenses(ie.getAnnualExpenses());
selfEmployed2.getIncomeExpenses().add(copy);// on this line it sets to copy fields id, and selfEmployed, that was in ie
}

Related

MAUI+ASP.NET DTOs

I have a project consisting of 2 parts:
ASP.NET API using Entity Framework
.NET MAUI Client App
I use DTOs for comunication from/to the API in order not to expose other properties of my entities. Thanks to this approach I was able to separate Entity data and data that are sent from the API.
At first I used these DTOs also in the MAUI UI. But after some time I started to notice that they contains UI-specific properties, attributes or methods that have no purpose for the API itself, so they are redundant in requests.
EXAMPLE:
1 - API will receive request from MAUI to get exercise based on it's name
2- ExerciseService returns: ExerciseEntity and ExerciseController use AutoMapper to Map ExerciseEntity -> ExerciseDto ommiting ExerciseId field (only admin can see this info in the DB) and returning it in the API response
3 - MAUI receives from the API ExerciseDto. But in the client side it also want to know if data from ExerciseDto are collapsed in the UI. So because of that I add IsCollapsed property into the ExerciseDto. But now this is a redundant property for the API, because I dont want to persist this information in the database.
QUESTIONS:
Should I map these DTOs to new objects on the client side ?
Or how to approach this problem ?
Is there an easier way how to achieve the separation ?
Because having another mapping layer will add extra complexity and a lot of duplicate properties between DTOs and those new client objects.
Normally if you use clean architecture approach your DTOs shoud contain no attributes and other specific data relevant just for some of your projects, to be freely usable by other projects in a form of dependency.
Then you'd have different approaches to consume DTOs in a xamarin/maui application, for example:
APPROACH 1.
Mapping (of course) into a class that is suitable for UI. Here you have some options, use manual mapping, write your own code that uses reflection or use some third party lib using same reflection. Personally using all of them, and when speaking of third party libs Mapster has shown very good to me for api and mobile clients.
APPROACH 2.
Subclass DTO. The basic idea is to deserialize dto into the derived class, then call Init(); if needed. All properties that you manually implemented as new with OnPropertyChanged will update bindings after being popupated by deserializer/mapper and you alse have a backup plan to call RaiseProperties(); for all of the props, even thoses who do not have OnPropertyChanged in place so they can update bindings if any.
Example:
our Api DTO
public class SomeDeviceDTO
{
public int Id { get; set; }
public int Port { get; set; }
public string Name { get; set; }
}
Our derived class for usage in mobile client:
public class SomeDevice : SomeDeviceDTO, IFromDto
{
// we want to be able to change this Name property in run-time and to
// reflect changes so we make it bindable (other props will remain without
// OnPropertyChanged BUT we can always update all bindings in code if needed
// using RaiseProperties();):
private string _name;
public new string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
// ADD any properties you need for UI
// ...
#region IFromDto
public void Init()
{
//put any code you'd want to exec after dto's been imported
// for example to fill any new prop with data derived from what you received
}
public void RaiseProperties()
{
var props = this.GetType().GetProperties();
foreach (var property in props)
{
if (property.CanRead)
{
OnPropertyChanged(property.Name);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public interface IFromDto : INotifyPropertyChanged
{
//
// Summary:
// Can initialize model after it's being loaded from dto
void Init();
//
// Summary:
// Notify all properties were updated
void RaiseProperties();
}
We can get it like: var device = JsonConvert.DeserializeObject<SomeDevice>(jsonOfSomeDeviceDTO);
We then can call Init(); if needed..
Feel free to edit this answer to add more approaches..

How to make JavaFX ListProperty modifiable only through custom methods

I have a private list and I don't want that it can be modified from outside in general. Just adding from outside is allowed and only if the object is valid. Therefore I used to write it like this:
private List<Object> list = new ArrayList<>();
public List<Object> getList()
{
return Collections.unmodifiableList(list);
}
public void addObject(Object object)
{
if (isObjectValid(object)) //any validation
list.add(object);
}
Now for JavaFX purposes I turn the list to a property:
private ListProperty<Object> list =
new SimpleListProperty<>(FXCollections.observableArrayList());
To profit from the benefits of an property like data binding and the ListChangeListener I have to provide the property to the outer world. But then access to all methods of a list is provided, too. (To use a ReadOnlyListProperty has no effect since the list instance itself will never change.) What can I do to achieve all goals:
private ListProperty
ListChangeListener can be added from outside
Usable for binding dependencies from outside (the create methods form class Bindings)
No modifying of the property or list instance itself
Modifying of list content from outside only through my own methods
Not tested, but try:
private ListProperty<Object> list = new SimpleListProperty<>(FXCollections.observableArrayList());
private ReadOnlyListWrapper<Object> publicList = new ReadOnlyListWrapper<>();
and in the constructor:
publicList.bind(Bindings.createObjectBinding(
() -> FXCollections.unmodifiableObservableList(list.getValue()),
list));
then your accessor method is
public ReadOnlyListProperty<Object> getList() {
return publicList.getReadOnlyProperty();
}

Cannot Update Entity Using EF 6 - ObjectStateManager Error

I'm trying to update an entity using Entity Framework version 6.
I'm selecting the entity from the database like so...
public T Find<T>(object id) where T : class
{
return this._dbContext.Set<T>().Find(id);
}
And updating the entity like so..
public T Update<T>(T entity) where T : class
{
// get the primary key of the entity
object id = this.GetPrimaryKeyValue(entity);
// get the original entry
T original = this._dbContext.Set<T>().Find(id);
if (original != null)
{
// do some automatic stuff here (taken out for example)
// overwrite original property values with new values
this._dbContext.Entry(original).CurrentValues.SetValues(entity);
this._dbContext.Entry(original).State = EntityState.Modified;
// commit changes to database
this.Save();
// return entity with new property values
return entity;
}
return default(T);
}
The GetPrimaryKeyValue function is as so...
private object GetPrimaryKeyValue<T>(T entity) where T : class
{
var objectStateEntry = ((IObjectContextAdapter)this._dbContext).ObjectContext
.ObjectStateManager
.GetObjectStateEntry(entity);
return objectStateEntry.EntityKey.EntityKeyValues[0].Value;
}
Just for clarity. I'm selecting the original entry out as I need to perform some concurrency logic (that Ive taken out). I'm not posting that data with the entity and need to select it manually out of the DB again to perform the checks.
I know the GetPrimaryKeyValue function is not ideal if there's more than one primary key on the entity. I just want it to work for now.
When updating, entity framework coughs up the error below when trying to execute the GetPrimaryKeyValue function.
The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object of type 'NAME_OF_ENTITY_IT_CANNOT_FIND'
I've written many repositories before and I've never had this issue, I cannot seem to find why its not working (hence the post).
Any help would be much appreciated.
Thanks guys!
Steve
It seems like you are having issues getting the PK from the entity being passed in. Instead of trying to go through EF to get this data you could either use their Key attribute or create your own and just use reflection to collect what the key names are. This will also allow you to retrieve multiple keys if it is needed. Below is an example I created inside of LinqPad, you should be able to set it to "Program" mode and paste this in and see it work. Hack the code up and use what you may. I implemented an IEntity but it is not required, and you can change the attribute to anything really.
Here are the results:
Keys found:
CustomIdentifier
LookASecondKey
Here is the code:
// this is just a usage demo
void Main()
{
// create your object from wherever
var car = new Car(){ CustomIdentifier= 1, LookASecondKey="SecretKey", Doors=4, Make="Nissan", Model="Altima" };
// pass the object in
var keys = GetPrimaryKeys<Car>(car);
// you have the list of keys now so work with them however
Console.WriteLine("Keys found: ");
foreach(var k in keys)
Console.WriteLine(k);
}
// you probably want to use this method, add whatever custom logic or checking you want, maybe put
private IEnumerable<string> GetPrimaryKeys<T>(T entity) where T : class, IEntity
{
// place to store keys
var keys = new List<string>();
// loop through each propery on the entity
foreach(var prop in typeof(T).GetProperties())
{
// check for the custom attribute you created, replace "EntityKey" with your own
if(prop.CustomAttributes.Any(p => p.AttributeType.Equals(typeof(EntityKey))))
keys.Add(prop.Name);
}
// check for key and throw if not found (up to you)
if(!keys.Any())
throw new Exception("No EntityKey attribute was found, please make sure the entity includes this attribute on at least on property.");
// return all the keys
return keys;
}
// example of the custom attribute you could use
[AttributeUsage(AttributeTargets.Property)]
public class EntityKey : Attribute
{
}
// this interface is not NEEDED but I like to restrict dal to interface
public interface IEntity { }
// example of your model
public class Car : IEntity
{
[EntityKey] // add the attribure to property
public int CustomIdentifier {get;set;}
[EntityKey] // i am demonstrating multiple keys but you can have just one
public string LookASecondKey {get;set;}
public int Doors {get;set;}
public string Make {get;set;}
public string Model {get;set;}
}

How to load business objects inherited from data layer (new answers are welcomed)

I have a Data layer and Business layer in my App.
In data layer I have imported database tables as objects using entity framework.
One of them is Unit table for example.
Now in business layer I want to add some methods to Unit of data layer so I have this class:
namespace Business.Entity
{
public class Unit : Data.Unit
{
//Some business affairs here
}
}
And for loading units in UI I have created a repository in business layer :
public static IEnumerable<Data.Unit> LoadUnits()
{
return from entity in StaticDataContext.Units select entity;
}
Everything is good till now.
But I want to load a list of Business.Unit in UI so I wrote this one:
public static IEnumerable<Business.Entity.Unit> LoadUnits()
{
var result = (from entity in StaticDataContext.Units
select entity).ToList().Cast<Business.Entity.Unit>();
return result;
}
It compiles well but then I get this runtime error when binding it to a Grid:
InvalidCastException: Unable to cast object of type 'Data.Unit' to type 'Business.Entity.Unit'
Can any one say how to arrange the classes to be able to load business classes in UI ?
Thanks
You can not directly cast parent object to child object. Possible solutions for your problem:
Create in Business.Entity.Unit class a constructor accepting Data.Unit as argument and assigning all necessary properties, like:
namespace Business.Entity
{
public class Unit : Data.Unit
{
public Unit(Data.Unit parent)
{
// Assign proprties here
}
//Some business affairs here
}
}
After that you can do:
public static IEnumerable<Business.Entity.Unit> LoadUnits()
{
var result = (from entity in StaticDataContext.Units
select new Business.Entity.Unit(entity)).ToList().Cast<Business.Entity.Unit>();
return result;
}
Rewrite your Business.Entity.Unit class so that it does not inherit Data.Unit, but accepts Data.Unit entity as a constructor parameter, aggregates it (stores in a local private member) and presents wrapper properties and functions to operate on it
Remove your Business.Entity.Unit class entirely and implement all additional methods as extension methods.
I'd vote for the third one because IMHO it leaves code a bit cleaner and does not have overhead of introducing and managing additional entity.
Try following approach, return your class Business.Entity.Unit objects list rather than casting to another class.
public static IEnumerable<Business.Entity.Unit> LoadUnits()
{
var result = (from entity in StaticDataContext.Units
select new Business.Entity.Unit {
///set properties of this class as
Id = entity.ID, .. son
}).ToList();
return result;
}
I suggest you to go through ScottGu's article on Code-First Development with Entity Framework 4.

Grails, injecting/populating domain object with value from session

In my application many classes have common field 'company'. When application saves that objects, they must be filled with company (there is validation for that). Company is also kept in a session. Now, when I want to use domain class as a command object, company must be already filled or I get validation error. Is there any way to always fill company field, before any validation happens, so that I didn't have to do it manually every time.
(I tried custom data binder, but it does not work when there is no parameter in a request)
You could set the property just before the object is saved, updated or validated using the GORM events beforeInsert, beforeUpdate or beforeValidate.
In your domain you need something like that:
import org.springframework.web.context.request.RequestContextHolder
class Foo {
String company
...
def beforeInsert = {
try {
// add some more error checking (i.e. if there is is no request)
def session = RequestContextHolder.currentRequestAttributes().getSession()
if(session) {
this.company = session.company
}
} catch(Exception e) {
log.error e
}
}
}
If you want to bind a property before the process of binding, You can create a custom BindEventListener and register in the grails-app/conf/spring/resources.groovy
First of all, create your custom BindEventListener
/src/groovy/SessionBinderEventListener.groovy
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.TypeConverter
class SessionBinderEventListener implements BindEVentListener {
void doBind(Object wrapper, MutablePropertyValues mpv, TypeConverter converter) {
def session = RequestContextHolder.currentRequestAttributes().getSession()
mpv.addPropertyValue("company", session.company)
}
}
Second of all, register your BindEventListener
grails-app/conf/spring/resources.groovy
beans = {
sessionBinderEventListener(SessionBinderEventListener)
}
However, if your domain class does not hold a property called company, you will get InvalidPropertyException. To overcome this issue, create a list of classes which contain a property called company - See details bellow
/src/groovy/SessionBinderEventListener.groovy
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.TypeConverter
class SessionBinderEventListener implements BindEVentListener {
private List<Class> allowedClasses = [Foo]
void doBind(Object wrapper, MutablePropertyValues mpv, TypeConverter converter) {
if(!(allowedClasses.contains(wrapper.class))) {
return
}
def session = RequestContextHolder.currentRequestAttributes().getSession()
mpv.addPropertyValue("company", session.company)
}
}

Resources