Code First mapping - mapping

I'm trying to map a Department to an Employee.
This is the Department Class:
Class Department
Property DepartID As Integer = 0
Property DepartName As String
End Class
If I define the Employee Class as follows:
Class Employee
Property EmployeeID As Integer
Property DepartID As Integer
' Navigational Property
Overridable Property Depart As Department
End Class
As you can see, the structure is very simple. Basically the Employee Table stores a Department ID, and I would like to automatically populate the Department Property.
I am easily able to map the Foreign Key using Fluent API if I have the Foreign ID field defined in Employee:
.HasRequired(Function(e) e.Depart).WithMany.HasForeignKey(Function(e) e.DepartID).WillCascadeOnDelete(False)
However, I would like to acheive the same without defining an ID property (DepartID) in the Employee Table. It's just going to be a bit cleaner, as I don't have to have multiple ID fields. Is it possible?

I suppose you mean DepartID in Employee class (not table, see my comment). If so, you can use ForeignKeyNavigationPropertyConfiguration.Map method to map it without the FK in model.

Related

GORM: embed a class containing a reference to a domain class

Given:
User, File are domain classes
src/groovy/Container.groovy:
class Container {
User user
File file
Date dateCreated
}
grails-app/domain/WithContainer.groovy:
class WithContainer {
Container c
String text
static embedded = ['c']
}
I was aiming at mapping WithContainer to a table with the columns:
user_id | file_id | date_created | text
Is that achievable with GORM?
This setup yields:
org.hibernate.MappingException: Could not determine type for: User, at table: with_container, for columns: [org.hibernate.mapping.Column(c_user)]
Thanks
Container is not a domain class because it isn't defined under grails-app/domain/.
It may be that you are confused about the embedded attribute. Properties in the embedded list are persistent properties for which you want all of their attributes stored in the same table as the owning class (WithContainer in your case), as opposed to being stored in their own table and referenced with foreign keys. The property still needs be an instance of a domain class though.

Saving reference properties with just the foreign key in Entity Framework

I am sure this question has been asked before, so I apologize in advance, but am not sure of the correct keywords to include in my searches...
I am having trouble understanding the proper pattern for updating (or even inserting) an object when one of its properties is a collection of other properties in a disconnected environment (like a website). My issue has to do with the idea that a web application is only returning a collection of id's as opposed to the full object. I think the best way to explain this is with code snippets.
Given the following objects
Public Class User
Public Property UserId As Integer
Public Property Username As String
Public Property Roles As ICollection(Of Role)
End Class
Public Class Role
Public Property RoleId As Integer
Public Property RoleName As String
Public Property Users As ICollection(OF User)
End Class
Public Class EFDbContext
Inherits Entity.DbContext
Public Property Users As Entity.DbSet(Of User)
Public Property Roles As Entity.DbSet(Of Role)
End Class
A database is created with 3 tables - Users, Roles, and RoleUsers.
I know I can easily do the following
Dim db = New EFDbContext()
Dim r1 = New Role() With { .RoleName = "User" }
Dim r2 = New Role() With { .RoleName = "Admin" }
db.Roles.Add(r1)
db.Roles.Add(r2)
Dim u1 = New User() With { .UserName = "test1", .Roles = New List(Of Role) }
u1.Roles.Add(r1)
db.Users.Add(u1)
db.SaveChanges()
And it will save both new roles to the database (giving them RoleId values of 1 and 2 respectively), a new user (giving it a UserId value of 1) and a new Role-User entry with RoleId 1 and UserId 1.
However, when dealing with a disconnected scenario like a website, most people would have a View Model to represent the input from the user which then gets mapped back to the Entities. In addition, for values representing the Roles, the data coming back would most likely only contain the unique key representing the Role. For example,
Public Class UpdatedUserViewModel
Public Property UserId As Integer
Public Property Username As String
Public Property RoleIds As ICollection(Of Integer)
End Class
...
...
Dim userEntity = db.Users.Find(user.Values.UserId)
AutoMapper.Mapper.Map(userValues, userEntity)
So while the userEntity.Roles collection may contain a single item, the mapper probably just added the entry with something like
ForMember(Function(u) u.Roles, Sub(m) m.MapFrom(Function(su) su.RoleIds.Select(Function(r) New Role() With {.RoleId = r})))
And now we come to the problem, when the SaveChanges() method is called, EF throws a Validation error because the .RoleName property is Nothing.
How does this situation get handled? Are we supposed to manually loop through the Roles and fetch each one from the database? Can we not use mapping tools? Do I give bogus values for the "missing" properties and then loop through and mark them as Unchanged?
I know this was long but I thought the walk-throughs would be helpful...
Thanks.
You can use this algorithm
Start with the root entities.
For each root entity, e.g. a of type A, set a's properties except for navigation properties (at least all the mandatory ones (non-nullables))
Add the As to the context.
Next prepare child entities (entities that must have exactly 1 A) e.g. b of type B.
Set b's properties (except navigations, at least all non-nullables).
For each b, add b to its a (e.g. a.Children.Add(b)).
Continue with child entities of above
...
Save and apply changes
If you have an entity with a non-nullable navigation that already exists in DB and has not yet been accessed via context, you can set the relationship by ID (assuming you've mapped the FK to a property in the model) instead of setting the entity itself.
If your IDs are not store generated, make sure you set them too. If they are, make sure they are defined as store generated in EDMX.
If you have FKs in the DB, make sure the EDMX is aware of them so that the inserts will happen in the correct order (or if using Oracle you can try using deferred constraints instead if you want).

Grails - Multiple Tables in Single Domain Class

I have two tables with a common primary key. Now i want to get data from that both tables and show in single view using that primary key.
How i can get both table data in single domain class? How can i specify mapping?
For Example
Table-A and Table-B both are in single schema ABC
class X {
int id
String name
static mapping = {
table name: "Table-A", schema: "ABC"
columns {
name column:'name'
}
}
}
now i want to get address from table-B so that my view looks like below
ID NAME ADDRESS
2 HSJHD 23 X-Street Washington USA
How to get two table data in single domain class?
This sounds like a foreign key relation, you would simply use belongsTo in each object (provided a one-to-one relationship).
http://grails.org/doc/latest/ref/Domain%20Classes/belongsTo.html
Otherwise you could create a database view on your database, then create a domain object to match that view. Creating a domain based on a database view is identical to creating a domain based on a table.
Few options
Just use hql to query and join on the primary key
Create a view from the two tables, and map new table to that view
Use belongs to and when u access one object then access the other
You will need to use constraints: http://www.grails.org/doc/2.0.x/ref/Constraints/Usage.html
and http://www.grails.org/doc/2.0.x/guide/single.html#constraints

single entity for different tables

I have same type of tables
ProductCodeTable, CountrycodeTable etc
All have key, value as their fields
When I use entity frame work,
Can I have a single entity for all these tables such that I can formulate different queries to get data from different tables?
You can create a base class for all of them and create sub class for each entity
public abstract class LookUpEntity
{
[Key]
public int Key { get; set; }
[Required]
public string Value { get; set; }
}
[Table("ProductCodeTable")]
public class ProductCode : LookUpEntity
{
}
This way you can model the relationships also and later if you wanted to add specific properties to those look up entities with out affecting other entities.
You can create a view with a Union of all tables like this:
create view AllKeyTables as
SELECT 'Product' as table, Productkey as Key, nameProduct as name
FROM ProductCodeTable
UNION
SELECT 'Country' as table, CountryISO as key, CountryName as name
FROM CountrycodeTable
UNION
...
Then update EF model and check 'table' and 'key' fields as Entity Primary Key.
Next question you will do is: 'How can I make a relation between this Entity and existing Entities?' The answer is 'you can't because EF is not able to join Entities between other fields than primary key'. Then, before implement this solution, be sure that this is you are looking for.
EF supports this only if you model it as inheritance (#Eranga showed it in code-first approach). You will have single base entity and derived entity for each table so you will not avoid having different type for each table. Otherwise the answer is no.
Inheritance will put additional requirements on data in your tables. For example Ids will have to be unique among all tables. So if ProductTableCode will have record with Id 1, CountryCodeTable (and any other code table) mustn't have record with Id 1.
Also inheritance in EF can produce nasty and very poorly performing queries.

How do I use Fluent nHibernate to map a multi-table entity using a foreign key from the primary entity using an FK->PK relationship?

This is the basic example from hbm-style nhibernate.
http://ayende.com/blog/2327/multi-table-entities-in-nhibernate
public class Person
{
public int PersonId {get;set;}
public string Name {get;set;}
public string AddressStreetAddress {get;set;}
public string AddressZipCode {get;set;}
}
In the database, Person has an Id primary key, a name field, and an address foreign key. Address has its own primary key, a street address field and a zip code field.
The correct answer is "Don't do it.". Unfortunately I'm stuck with an entity object that exposes the Id and Name of another entity and those are used elsewhere still. At the moment, this object won't be persisted back to the database through nHibernate.
I think the way to do this is to use the address as the table of the entity and add the Person fields from the Join(). What are the consequences of doing this as an intermediate step in a change-over?
I think the way to do this is to use
the address as the table of the entity
and add the Person fields from the
Join(). What are the consequences of
doing this as an intermediate step in
a change-over?
This was a bad idea because the only Id you could map to is the Id of the address which can be shared between multiple persons.
Instead, add a private/protected property for Address to Person, map Address and reference the address using the following Fluent call.
References(Reveal.Member<Person, Address>("Address")).Column("address_id")
Then, you can use AddressStreetName and AddressZipCode to pass through to Address.StreetName and Address.Zipcode. After that, it's a simple matter of refactoring the rest of the system to be sane again.

Resources