Is there better way rather than to fetch with predicate and see the number of results in order to check that the attribute exists when adding it into managed context? I'm trying to make an attribute unique for given entity...
I think you may have scrambled your nomenclature. You don't add attributes to context. You add managed objects which are defined by entities which have attributes. You could be asking about two different types of test.
If you're asking whether a means exist of testing if a managed object already exist with the exact same attributes of the one you planning on inserting, the answer is no. Since entities can be arbitrarily complex and since it takes only literally one bit different to make them logically distinct, there is no means of testing whether two objects are logically identical i.e. have the same attributes and relationships, without fetching them and testing them.
If you're asking whether you can test for a unique value of an attribute of a particular entity then you can. First you fetch on a property using [NSFetchRequest setProperty:] and then set you're predicate for the sought value. When walking relationships, you can use the Set and Array Operators to find managed objects with unique values.
Related
In Hibernate Search 5 I had several custom bridges that populated the same field. That was handy so that I can perform a query on just one field. Now if I try to do it I receive this error:
HSEARCH600034: Duplicate index field definition: 'attributes'. Index field names must be unique. Look for two property mappings with the same field name, or two indexed-embeddeds with prefixes that lead to conflicting index field names, or two custom bridges declaring index fields with the same name.
I have not found a way to get an existing field from the PropertyBinding Context when implementing the PropertyBinder, only the documented way to add new fields:
IndexFieldReference<String> attributesField = schemaElement
.field("attributes", f -> f.asString())
.toReference();
Am I missing something or is no longer possible and I need to add new fields?
How can I reuse a field in several bridges in Hibernate Search 6?
At the moment, you cannot.
This limitation is a side effect from the (many) sanity checks that Hibernate Search 6 performs on startup, which prevent common mistakes and indirectly allow a more intuitive behavior in the Search DSL.
Your options are pretty much this:
Either you refactor your bridges to regroup all code that contributes to the same field in a single bridge (either a TypeBridge, or a PropertyBridge applied to a non-persisted getter that returns an aggregated list of all values you're interested in).
Or you change your bridges to each contribute to its own field, and change your search code to target all these fields at once; most (if not all) predicates allow targeting multiple fields in the same predicate.
The second solution is also the recommended way of indexing, since it produces more accurate relevance scores.
EDIT: If you go for solution 2, this (not yet implemented) feature might be of interest to you: https://hibernate.atlassian.net/browse/HSEARCH-3926
Can we use List<ValueObject> inside entity? or we should use them as List<entity>?
When I use 'List<Discount>' inside my 'Product' entity class, entity framework creates a 'Discount' table with a generated column id.
Is it OK that i have defined Discount as List of value objects?
When a value object is used as a list, is it better to use it as an entity with its identity?
The second question is about updating 'List<Discont>' inside entity. how can I update this value object list inside its entity( add,remove discount)?
thanks
As mentioned in the comments by #Ivan Stoev, your domain model is not your database model. You need to model your domain in an object-oriented way with, ideally, no regard for the database. BTW, having some identifier in a Value Object does not make it an Entity. An Entity would, however, always require a unique identifier within that entity set but an identifier isn't the defining factor to make a class an entity (that would be whether it has its own lifecycle).
In the real world one would need to be pragmatic about the general guidance. For instance, if you need an identifier of sorts for your value object then that is fine. However, it may be that there is already something there that may be used. In an OrderItem one would use the ProductId since there should only be a single item for each product. In your Discount scenario perhaps there is a DiscountType where only unique discount types are permitted. On the point of mutable value objects, the reason a value object is usually not mutable is that it represents a particular value. You would never change 10 since that would be another value. It would seem that one would be changing 10 to, say, 15 when you need 15 but, in fact, that 15 is another value object. Again, one would need to be pragmatic and in many circumstances we end up using a Value Object that isn't as primitive as a single value so it may make sense to alter something on the value object. An order item is certainly not an entity but one would need to change the Quantity on the item every-so-often. Well, that may be another discussion around Quote/Cart vs Order but the concepts are still applicable.
On another note, I tend to nowadays define any "value object" that exists only within an aggregate as a nested class within the aggregate. I would not have Order and OrderItem classes but instead an Item class within the Order class... Order.Item. That is a design choice though but I thought I'd mention it.
C# 9 introduces record reference types. A record provides some synthesized methods like copy constructor, clone operation, hash codes calculation and comparison/equality operations. It seems to me convenient to use records instead of classes in general. Are there reasons no to do so?
It seems to me that currently Visual Studio as an editor does not support records as well as classes but this will probably change in the future.
Firstly, be aware that if it's possible for a class to contain circular references (which is true for most mutable classes) then many of the auto generated record members can StackOverflow. So that's a pretty good reason to not use records for everything.
So when should you use a record?
Use a record when an instance of a class is entirely defined by the public data it contains, and has no unique identity of it's own.
This means that the record is basically just an immutable bag of data. I don't really care about that particular instance of the record at all, other than that it provides a convenient way of grouping related bits of data together.
Why?
Consider the members a record generates:
Value Equality
Two instances of a record are considered equal if they have the same data (by default: if all fields are the same).
This is appropriate for classes with no behavior, which are just used as immutable bags of data. However this is rarely the case for classes which are mutable, or have behavior.
For example if a class is mutable, then two instances which happen to contain the same data shouldn't be considered equal, as that would imply that updating one would update the other, which is obviously false. Instead you should use reference equality for such objects.
Meanwhile if a class is an abstraction providing a service you have to think more carefully about what equality means, or if it's even relevant to your class. For example imagine a Crawler class which can crawl websites and return a list of pages. What would equality mean for such a class? You'd rarely have two instances of a Crawler, and if you did, why would you compare them?
with blocks
with blocks provides a convenient way to copy an object and update specific fields. However this is always safe if the object has no identity, as copying it doesn't lose any information. Copying a mutable class loses the identity of the original object, as updating the copy won't update the original. As such you have to consider whether this really makes sense for your class.
ToString
The generated ToString prints out the values of all public properties. If your class is entirely defined by the properties it contains, then this makes a lot of sense. However if your class is not, then that's not necessarily the information you are interested in. A Crawler for example may have no public fields at all, but the private fields are likely to be highly relevant to its behavior. You'll probably want to define ToString yourself for such classes.
All properties of a record are per default public
All properties of a record are per default immutable
By default, I mean when using the simple record definition syntax.
Also, records can only derive from records and you cannot derive a regular class from a record.
I have an entity, and I want to fetch a certain attribute.
For example,
Let's say I have an entity called Food, with multiple attributes. I want to select all categories, which is an attribute on each food item. What's the best way to accomplish this in Core Data?
Just run your fetch request and then use valueForKey: to extract all of the attribute values. If your model contains lots of objects, you can set the fetch limit and offset (and sort descriptor) to page through the items. When doing this you should also set the fetch request to not return objects as faults.
Just remembered there is an alternative. You can set the properties to fetch and then set the result type to NSDictionaryResultType. You still need to do the iteration but this will return the minimum data possible.
EDIT: I think I misunderstood your question. It seems that you only want to fetch a property of an object, not the object itself (e.g. the attribute but not the entity)? I don't believe core data is going to work that way...it's an object graph rather than a database, as the person above mentioned. Research how Core Data "faults", automatically retrieving dependent objects as they are needed. I left the advice below in case it still applies, though I'm not sure it will.
You can add a predicate to your search in order to fetch only objects which meet certain criteria; it works like an "if" statement for fetching. Here's Apple's documentation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/Reference/NSPredicate.html
And a tutorial:
http://www.peterfriese.de/using-nspredicate-to-filter-data/
All that said, the necessity really depends on how many objects you're fetching. If it's not causing any performance hit, there's not necessarily anything wrong with fetching a few un-needed objects. Solve problems, in other words--don't "optimize" things that were working fine. If your model contains a ton of objects, though, it could be expensive to fetch them all and you would want to use a predicate.
You can only fetch whole objects, but you can only fetch objects that have a perticlar attribute using nspredicate in your fetch request. See the code snippet in Xcode in the snippet section. Look for fetch request in the find field and drag out the snippet with the nspredicate code. You can set the predicate to only find the objects that satisfy this predicate. Hope this helps!
I want to be able to look through all the attributes of an Entity and find the most popular one. I know it has something to do with NSPredicate, but I can't quite wrap my mind around to achieve it.
One possible solution:
Fetch all the entities and loop through it and sort the attributes into different arrays, from there count the items in the arrays to determine the most popular/common one.
Although this might work I'm just wondering if there's an easier or 'cleaner' way of doing it.
Update:
Thanks #Caleb. Let me clarify, I'm looking for a single attribute value that's most often used by instances of a given entity.
That is really a dirty descision.
I would suggest you to make a new entity, say, AttributeCounter, with two attributes - name and count, and every time you add an attribute to a person, change this entity.
But that would only be good descision if you have a few different attributes and lots of persons. If not, here is another approach, that is quite simple:
Get all the enteties with first attribute not nil,count,add to array
Sort it
Here you are