I am new to db4o.
I have this question in mind:
when the object are retrieved from DAL, maybe it will update in Business layer, then we lost it's original property, so when it comes to updating how can I find which one is the original object in the database to update?
You need to be more precise about "the object". If you modify the object instance's properties, simply storing it again will perform an update:
MyClass someInstance = ObjectContainer.Query<MyClass>().FirstOrDefault();
someInstance.Name = "NewName";
someInstance.PhoneNumber = 12132434;
ObjectContainer.Store(someInstance); // This is the update call
[This is just pseudo-code]
So you don't need to match objects to each other as you would have to when using an RDBMS.
However, you need to make sure you are not using a different instance of ObjectContainer, because a different container will not know these objects are the same instance (since there is no ID field in them).
Your application architecture should help to do this for most workflows, so there should be really only one IObjectContainer around. Only if timespans are really long (e.g. you need to store a reference to the object in a different database and process it somehow) it'd use the UUID. AS you already pointed out, that requires to store the ID somewhere else and hence complexifies your architecture.
If you however intend to create a new object and 'overwrite' the old object, things get somewhat more complicated because of other objects that might refer to it. However, this is a somehwat pathological case and should typically be handled within the domain model itself, e.g. by copying object data from one object to another.
You should load the object via its ID:
objectContainer.get().ext().getByID(id);
or via its UUID:
objectContainer.get().ext().getByUUID(uuId);
See the docs for the latter one. For an explanation see the answer here or the docs here. In short use uuid only for long term referencing.
Related
I am using realm and I am not sure about this.
I have two option to do in Post. One is to save entire owner object and another is to save only user object ID. If I save entire object, is it object by reference? I don't want to increase database size.
The reason why I want to store entire object is that it is easy to access. It is like Post.User.email. I don't need to query. I read through realm though. https://realm.io/docs/objc/latest/
Thanks in advance.
No need to go by ID. In Realm, when you add a property of another RealmObject type, that will store the reference, not the entire object. So it will not take more space on disk than what you are expecting.
I am not sure if your diagram reflects your actual types, but note that when using collections, you want them to be of type RealmList<>, not Array<> (I am assuming you are writing C# as you referred to the Xamarin docs).
I have a model some instances of which I need to persist. Only some, not all, since persisting all instances would be wasteful. The model has primaryKey of type Int
I need to be able to pass all objects from background to main thread since Realm objects can only be used by the thread on which they were created. Current version of Realm Swift (0.94) does not seem to support handing the object over to another thread directly.
For persisted objects (the ones saved to storage with write) this is not a problem, I can fetch the object on another thread by primaryKey.
Unpersisted objects, however, are problematic. When I create a new object with the same primaryKey in background (I suppose it should be treated as the same object since it has the same primaryKey) and try to fetch it on the main thread (without persisting changes with write since I don't want in in the storage), I seem to get the old object.
I see the following solutions to this problem:
1) persist all objects (which is undesirable and otherwise unnecessary)
2) keep separate model for the objects I want to persist (leads to code duplication).
3) use init(value: AnyObject) initializer which creates unpersisted object from a Dictionary<String, AnyObject> (would probably require manual copying of object properties to dictionary, tedious and potentially error-prone)
Are there any better solutions?
Offtopic: I haven't tried Realm for Android, is situation any better with it?
You are free to pass unpersisted objects between threads as you wish -- only persisted objects cannot yet be handed over between different threads.
I think your problem is that you are creating two objects that you want to be the same object and there is no way the system can know which one you want.
The solution is as simple as it is generic: create a new object only after checking that its unique attribute does not exist already. This should work equally well with persistent and non persistent objects. Obviously, you need to have a central, thread safe in-memory repository where you can go and create new objects.
You write:
I seem to get the old object.
There should not be any old object if you have checked before.
I'm making a simple bank account tracker, for self-instructional purposes. I'm using Core Data to store three entities, related as in the screenshot:
WMMGTransaction objects are simply stored as they are recorded, and extracted as needed to feed tableviews and detail views. This will be done via NSFetchedResultsController and a predicate. I'm using MagicalRecord to access Core Data, if that matters.
My question is this:
When I pass WMMGAccount data from one VC to another, such as when creating a new account, or when selecting one from a list (via delegation as a rule), does it matter if I pass a reference to the entire entity, or can I just use an NSString bearing the .name of the account and identify the account when required with a predicate and an NSFetchedResultsController? I guess this is a strategy question, and may generate discussion, rather than having a cut and dried answer, but I'm wrestling with it, so I thought I'd ask.
It sounds like you're asking if you should pass an object to the code that needs it, or if you should pass information that could be used to look up the same object again.
Unless you need to use the managed object on a different thread or queue, you should always pass the actual object. No sense re-fetching an object you already have. It's extra work and code complexity that (unless there are some unusual extenuating details you didn't mention) won't help in any way.
If you are needing to use the object on a different queue or thread, passing information that can be used to look it up is the correct approach. But in that case-- don't pass the value of one of the properties. Use the managed object ID.
Core Data won't force name values to be unique, while the object's managedObjectID is unique. It's also faster when retrieving the object, because you can use objectForID: or existingObjectForID: instead of performing a fetch.
I have this problem of confusing when to include the entire object as a property of another object, or just its ID. It seems that if I include the entire object, the calls to load the containing object will unnecessarily also load the included object when I probably only need references. What is propert approach?
Generally always refer to another object.
Many ORM technologies have the idea of "proxies" and "lazy loading", meaning, unless you reference the object, it won't load it.
I prefer to include the object itself, since one object actually has a relationship with another actual object -- the object ID is just an implementation detail. To deal with the problem of unnecessary calls, look into "lazy loading".
Only include the other object if you need the details.
in MVC use a ViewModel ideally and not your entities. Your ViewModel contains only what it needs, so for example OrderEditViewModel would contain a customerid unless you want to display the custom name, in that case you would include the fields from customer. Some people recomend you flatten out your objects to a view model, so you dont have OrderEditViewModel.Customer.CustomerId but instead ORderEditViewModel.CustomerId. Automapper can help you do this (As well as valueinjecter - note the spelling)
If you must include an ID ensure when you save back to the database your update include a clause to say 'where id=#customerId and (logic here to ensure your user actually has access to that customerid and root object)
I have mvcsecurity.codeplex.com to help encrypt record ids on a web page to prevent against tampering as well (it helps but you should still have something in your query to prevent field tampering so an attacker cant add someone else's customer id for example_)
I go more into parameter tampering in MVC here if anyone is interested:
http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=hack-proofing-dotnet-app
My suggestion would be to always think about the design and not about performance. Performance can be tweaked but design can't. So, if the two objects have that kind of a relationship where Aggregation/Composition is required, you should do that.
But, if your containing object only has to deal with the ID (for e.g. passing it to a different object which processes the ID to do something) then you can keep the ID field only. No need to expose the whole object (but make sure that your containing object does not need to know anything about the other object.).
When getting an object from the DB, should the object's properties also be loaded? There seems to be these approaches.
Create well-formed, fully-loaded objects.
Pro: No need to check if a property has been loaded; it has. Pass it around and don’t worry about parts of the object not being there.
Con: Where do you stop? If an object has an object, and that object has an object, and that object has 40 objects as properties, etc… Do you load the whole DB? Or do you make a decision in the BLL as to what constitutes a well-formed object, and load those properties?
Don’t load any properties that are other objects.
Pro: Quick, no loading unnecessary properties.
Con: Code has to be constantly written to check if properties are populated.
Lazy-loading: only load properties when they are first used.
Pro/Con: Not sure what to say about this approach. It seems intuitively wrong.
Is there another approach? What approach is the best?
And finally, what about properties that can be null? For example, a car may not have a PreviousOwner object. Do you set it to null? An empty PreviousOwner object? Does that property belong in another class then?
There's no easy answer to your question because it depends on what you're trying to achieve.
It looks like you expect a more or less complete object graph to be loaded from the database (i.e. with relationships between multiple object types and the objects themselves stored in the database).
If this is the case, I would look into using the Object Relationship Mapper that's convenient in my language of choice.
As to how much of the object graph is being loaded, the model employed by Apple CoreData's system is objects not yet retrieved are marked as faulty (they call the concept "faulting" - it's described in Limiting the Size of the Object Graph: Faulting. This is a play on the lazy loading concept you described yourself.