I am trying to do the simple, something I've done countless times in SQL, but I have Table A, it has a id column as the primary key - which I'm not using here. Table B also has one, also not used for this.
I want to get all the rows in B, that match on a column that is in A (int) and have them show up in that entity.
Thus: Let's for sake of argument say that both tables have a column called "Joiner", If I was writing this in SQL, I'd say:
Select A.*, B.* from TableA A
Join TableB B on A.Joiner = B.Joiner
Easy right? Couldn't be a more common thing unless it was A.Id... But it isn't
So, in Entity Frameworks Core, I want to get an A by id, .Include B.
Now, I get A.Bs which is a list of all the B's that match the A's on their Joiner fields.
Super Easy right?
I'm using the EntityMappingConfiguration<A> and EntityMappingConfiguration<B> to define the mapping, Overriding the 'Map()' Method, so things that tell me how to modify that would be most helpful.
I've been able to have it create mappings that are looking for B.Joiner = A.Id, And things that are looking for an array of B to exist in A (that just doesn't even make sense)...
Oh, there are MANY B's that match A's value, and could be that same value in many other A's (From what I can tell it is a Many to Many relationship, except that you would never ask for B's matching A records.) The idea being that we can update A's Joiner value, and have it switch to a different B, and thus, be able to pick up other configuration columns in B..
Just seems like this should be a slam dunk, yet, none of the Entity Framework (core) guru's seem to be able to do this.
In reference to code examples, I have about 200 things that don't work. Here is one example:
public class TableAMap: EntityMappingConfiguration<TableA>
{
public override void Map(EntityTypeBuilder<TableA> b)
{
b.ToTable("TableA");
b.HasKey(x => x.Id);
b.Property(x => x.Id).UseIdentityColumn();
b.HasMany(x => x.TableBs)
.WithOne()
.HasForeignKey(x => x.Joiner);
}
}
The class TableA has a Joiner field that is an Int and a Joiners field that is public virtual ICollection Joiners{ get; set; }, (In my case, I'm calling TableB the same as the field, so both would be 'Joiner' in this case.) But it wants to use the Id/TableAId to join. I've tried using HasPrincipalKey () - which seems like exactly what I'm wanting to do, except that there is a comment on the documentation that says "if there is not a unique constraint, it will add one" - sigh, there are multiple duplicate values, so nope, not unique, so please don't automatically add the constraint!
I'll try to write up an example that is simple (and isn't code that I can't share)
Related
I want to do one query, and I thought I could write it in the following two ways:
SELECT c, p
FROM MyBundle:Car c
JOIN c.person p
WHERE
p.name = :name
and
SELECT c, p
FROM MyBundle:Person p
JOIN p.car c
WHERE
p.name = :name
Since in both cases I was asking for "c, p" in that particular order, I was expecting the query to return the same thing, however, in the first case the object I get is of the type Car and on the second case is of type Person.
I don't understand why this happens, any light would be appreciated.
The first one says: give me every car attached to a person, where person's name is :name. Naturally this is a list of cars.
The second says give me every person attached to a car, where person's name is :name. Naturally this is a list of persons.
Since they are joined, doctrine eager loads the related entity as a field of the primary select, which is indicated by the from clause.
Basically, this is object oriented view, this is how dql works. Your contention that they should be the same is a tuple-oriented view, which is how sql works. Mastering this concept is essential for effective use of doctrine.
You have a query say :-
select p from profiles p, group g where p.profileId = g.profileId
How will you implement it using JDO. It could be basic but I am new to JDO and was not able to goolge something meaningful.
In JDOQL you dont really have something like a JOIN. As #sihaya mentioned, retrieving a object will also fetch all of its members (depending on the configured fetch type ("eager" will load everything and "lazy" will load it later))
Looking at the docs, you can use something similiar, called "unbound variables":
Unbound variables, which serve as a replacement for the JOIN operation of SQL
Unbound variables are supported by ObjectDB, but considered optional by JDO. Queries with unbound variables are similar to JOIN queries in SQL because every combination of variables has to be checked for every candidate object. Just like JOIN queries in SQL, queries with unbound variables may become very slow, so caution is needed when using them.
Here is the link: https://www.objectdb.com/database/jdo/manual/chapter7
In JDO and other object-relational mapping frameworks such as JPA the join condition for a relation between two entities is inferred from the meta-model.
In your example you presumably have two entities Profile and Group and a n-1 relationship from Group to Profile. Then given the following entities:
#PersistenceCapable
public class Group {
private Profile profile;
...
}
and
#PersistenceCapable
public class Profile {
...
}
Executing the following JDO query will select all profiles that are referenced by a group:
select g.profile from Group g
This is similar to a question I asked earlier. The answers to that question partially solved my issue, but I'm still having some issues in trying to perform the kind of search I specified there; furthermore, I'm simply having trouble understanding how Hibernate chooses what to return in different scenarios.
Here's my mapping:
Client {
#OneToMany(mappedBy="client",cascade=CascadeType.ALL)
private Set<Group> groups = new HashSet<Group>();
}
Group {
#ManyToOne (cascade=CascadeType.ALL)
private Client client = new Client();
private String name;
private String state; //two char state code
private String extId; //unique identifier; candidate key, but not the #Id.
}
Queries by name are inline (e.g., like with wildcards on both ends of the param); state and extId are by equality.
The following query returns a single client, with only the matching group attached, even if other groups are associated to the client (note again that extId will only return one group):
select distinct client from Client as client
inner join client.groups as grp
where grp.extId = :extId
This query returns a single client, but with all associated groups attached, regardless of whether the group's state code matches the criteria:
select distinct client from Client as client
inner join client.groups as grp
where grp.state= :state
Finally, this query returns a separate copy of the client for each matched group, and each copy contains all of its associated groups, regardless of whether the group's name matches the criteria:
select distinct client from Client as client
inner join client.groups as grp
where grp.name like :name
I'm new to Hibernate, and I'm finding it immensely frustrating that I'm unable to predict what is going to be returned from a given query. All three queries are nearly identical, except for some small changes in the WHERE clause, yet I get radically different results for each. I'd spent time reviewing the documentation, but I'm missing wherever this behavior is explained. Can anyone help shed some light on this?
Finally, what I really need to do is to return Clients when querying by Group, and have the client only contain the Groups which match the search criteria. Is there a single-shot way I can construct an HQL query to do so, or will I have to do multiple queries and build my objects up in code?
Thanks.
The answer to this is twofold. One, there was a problem with the test harness, which was (sensibly) using transaction rollback to create test instances without leaving artifacts in the database. This was the source of my odd responses in the queries.
I managed to return just the values I wanted in the collections by simply changing to an outer fetch join.
I have an Entity Framework 4 design that allows referenced tables to be deleted (no cascade delete) without modifying the entities pointing to them. So for example entity A has a foreign key reference to entity B in the ID field. B can be deleted (and there are no FK constraints in the database to stop that), so if I look at A.B.ID it is always a valid field (since all this does is return the ID field in A) even if there is no record B with that ID due to a previous deletion. This is by design, I don't want cascading deletes, I need the A records to stick around for a while for auditing purposes.
The problem is that filtering out the non-existing deleted records is not as easy as it sounds. So for example if I do this:
from c in A
select A.B.somefield;
This results in a OUTER JOIN in the generated SQL so it's picking up all the A records even if they refer to missing B records. So, the hack I've been using to solve this (since I can't figure out a better way!) is do add a where clause to check a string field in the referenced B records. If that field in the B entity is null, then I assume B doesn't exist.
from c in A
where c.B.somestringfield != null
select A.B.somefield;
seems to work IF B.somestringfield is a string. If it is an integer, this doesn't work!
This is all such a hack to me. I've thought of a few solutions but they are just not practical:
Query all tables that reference B when a B is deleted and null out their foreign keys. This is so ugly, I don't want to have to remember to do this if I add another entity that references B in the future. Not to mention a huge performace delay resolving all the references whenever I delete something.
Add a string field to every table that I can count on being there that I can check to see if the entity exists. Blech, I don't want to add a database field just for this.
Implement a soft delete and keep all the referencial integrity intact - essentially set up cascading deletes, but this is going to result is huge database bloat since I can't clean up a massive amount of records due to the references. No go.
I thought I had this problem licked with the "check if a field in the referenced entity is null" trick but it breaks under conditions that I don't completely understand (what if I don't have any strings in the referenced table? What kinds of fields will work? Integers won't.)
As an example if I have an integer field "count" in entity B and I check to see if it's null like:
from c in A
where c.B.count != null
select c.B.count;
I get a bunch of records with null for count mixed in with the results, and in fact the query bombs out with an "InvalidOperationException: The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."
So I need to do
from c in A
where c.B.count != null
select new { count = (int?)c.B.count };
to even see the null records. So this is pretty baffling to me how that query can result in null records in the results at all.
I just discovered something, if I do an explicit join like this, the SQL is INNER JOIN and everything works great:
from c in A
join j in B on A.B.ID equals j.ID
select c;
But this sucks. I'll have to modify a ton of queries to add explicit join clauses instead of enjoying the convenience of the relationship fields I get with the EF. Kinda defeats the purpose and adds a buch more code to maintain.
When you say that your first code snippet creates an OUTER JOIN then it's the case because B is an optional navigation property of entity A. For a required navigation property EF would create an INNER JOIN (explained in more detail here: https://stackoverflow.com/a/7640489/270591).
So, the only alternative I see to your last code snippet (using explicit join in LINQ) - aside from using direct SQL - is to make your navigation property required.
This is still a very ugly hack in my opinion which might have unexpected behaviour in other situations. If a navigation property is required or optional EF adds a "semantic meaning" to this relationship which is: If there is a foreign key != NULL there must be a related entity and EF expects that you don't have removed the enforcement of the FK constraint in the database.
I have map the entities in .hmb.xml and define attribute for all entity in classes.
I have some basic accomplishment and get all the record using below code.
public List<DevelopmentStep> getDevelopmentSteps()
{
List<DevelopmentStep> developmentStep;
developmentStep = Repository.FindAll<DevelopmentStep>(new OrderBy("Id", Order.Asc));
return developmentStep;
}
I have check from net that we can write HQL, Now the problem is how to execute this HQL like..
string hql = "From DevelopmentSteps d inner join table2 t2 d.id=t2.Id where d.id=IDValue";
What additional Classes or other thing I need to add to execute this kind of HQL?
Please help me ---- Thanks
To write dynamic queries, I recommend using the Criteria API. This is dynamic, because you have a single query for several different types and you also want to set the ordering dynamically.
The queries are always object oriented. You don't need to join by foreign keys, you just navigate through the class model. There also no "tables" in the queries, but entities.
Getting (single) instances by ID should always be done using session.Get (or session.Load). Only then NHibernate can also take it directly from the cache without database roundtrip, it it had already been loaded.
for instance:
public IList<T> GetAll<T>(string orderBy)
{
return session.CreateCriteria(typeof(T))
.AddOrder(Order.Asc(orderBy))
.List<T>();
}