code first, multiple bindings - entity-framework-4

I would like to map my entity class to a database table.
Table rows are: Id, IsActive, BelongsToId
(BelongsToId is a foreign key)
Entity properies are: Id, IsActive, BelongsToId, BelongsTo
(BelongsToId int, BelongsTo is an other entity class' instance)
Is it possible to bind both BelongsToId and BelongsTo properties to BelongsToId data attribute? How?
I try like this, but BelongsToId's value is zero:
partial class KeyConfig : EntityConfiguration<Entities.Key>
{
public KeyConfig ( )
{
Property(s => s.Id).IsIdentity();
Relationship(s => s.BelongsTo).FromProperty(s => s.Keywords);
Property(s => s.IsActive);
Map();
}
void Map ( ) {
MapHierarchy(s => new
{
s.Id,
BelongsToId=s.BelongsTo.Id,
s.IsActive,
}).ToTable("Keywords");
}
}

Related

How to convert native sql to grails/gorm

Can I convert this to GRAILS/GORM. If yes, any help please.
select b.id, b.username, b.first_name, b.last_name
from tb_user_orgpermissions a
inner join tb_user b on a.username = b.username
where
(a.department_id = :dept_id)
and (a.agency_id = :agy_id)
To create the equivalent query as a gorm criteria query, the first thing you need is domain classes (with proper associations) for each table. As an example, here's some pseudo code:
class User {
String username
String firstName
String lastName
static hasOne = [permission: UserPermission]
}
class UserPermission {
Department department
Agency agency
}
class Department {}
class Agency {}
In this example User has a one-to-one association to UserPermission.
With something like this in place you can create a criteria query (with projections):
User.withCriteria {
projections {
property 'id'
property 'username'
property 'firstName'
property 'lastName'
}
permission {
department {
eq 'id', dept_id
}
agency {
eq 'id', agy_id
}
}
}

OneToOne mapping with NHibernate and Breeze

Is it possible to make that kind of mapping work with breeze and NHibernate:
public class PeopleMap: BaseMapping<People>
{
public PeopleMap()
{
this.Property(x => x.FirstName);
this.Property(x => x.LastName);
}
}
public class PersonMap : JoinedSubclassMapping<Person>
{
public PersonMap()
{
this.Key(p=>p.Column("ID"));
this.Property(x => x.FirstName);
this.Property(x => x.LastName);
this.Property(x => x.InfoId, map =>
{
map.Insert(false);
map.Update(false);
}
);
this.ManyToOne(x => x.Info, map =>
{
map.Cascade(Cascade.All);
map.Column("InfoId");
});
}
public class PersonInfoMap : BaseMapping<PersonInfo>
{
public PersonInfoMap()
{
this.Property(x => x.Extra);
this.OneToOne(x => x.Person, map =>
{
map.Constrained(true);
map.PropertyReference(p => p.Info);
});
}
}
There is a table per subclass inheritance between people and person. The goal is to make a one to one association between person and personinfo. The mapping works fine in NHibernate. The metadata are generated and queries can be done. The only problem is I can't do a save.
var d = breezeService.manager.createEntity('Person',
{
FirstName: 'Laurent',
LastName: 'Nullens'
});
var l = breezeService.manager.createEntity('PersonInfo',
{
Extra: 'First data',
Person: d
});
d.Info = l;
The result is an exception because the Person entity is saved before the PersonInfo(foreign key exception). I saw in the samples a one to one with Order and InternationlOrder but in that sample both entities share the same primary key.
Is it possbile or is there any workaround like in the Order/InternationalOrder sample?
Have you looked at the breezjs NHibernate sample?
Please do ... and then report back if you can't find what you're looking for.

IQueryable to IEnumerable

public IEnumerable<Temp_Order> Get_Temp(string id)
{
//List<Temp_Order> data = new List<Temp_Order>();
IEnumerable<Temp_Order> data = db.Temp_Order
.Join(db.Items,
t_id => t_id.ItemId,
I_id => I_id.ItemId,
(t_id, I_id) => new { t_id.Quantity, I_id.ItemName })
.Where(x => x.ItemName == id);
return data;
}
In this method I want IEnumerable<Temp_Order>. So I will use this in controller and return to the view.
I'm getting this error:
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?) E:\WORK\Projects\RMS_Live\RMS_Live\Models\Order.cs
The Join is converting your query to an IEnumerable of an anonymous type. Add a Select on the end to cast is back to Temp_Order:
public IEnumerable<Temp_Order> Get_Temp(string id)
{
//List<Temp_Order> data = new List<Temp_Order>();
IEnumerable<Temp_Order> data = db.Temp_Order
.Join(db.Items, t_id => t_id.ItemId, I_id => I_id.ItemId, (t_id, I_id) => new { t_id.Quantity, I_id.ItemName })
.Where(x => x.ItemName == id)
.Select(a => new Temp_Order
{
ItemName = a.ItemName,
Property2 = a.Property2,
//snip
});
return data;
}
EDIT:
You indicate in the comments that you want all properties from both Temp_Order and Item which means you need another class. You can get away without creating another class, but it's much simpler in the long run. So first make your class, 2 ways spring to mind, you either replicate all the properties you need or just return the 2 objects, I'll use the latter:
public class OrderItem
{
public Temp_Order Temp_Order { get; set; }
public Item Item { get; set; }
}
Now your function becomes this:
public IEnumerable<OrderItem> Get_Temp(string id)
{
IEnumerable<OrderItem> data = db.Temp_Order
.Join(db.Items,
t_id => t_id.ItemId,
I_id => I_id.ItemId,
(t_id, I_id) => new OrderItem
{
Temp_Order = t_id,
Item = I_id
})
.Where(x => x.ItemName == id);
return data;
}
And in your view, make sure you set the model type to IEnumerable<OrderItem> and you can access all the properties like this:
#Model.Temp_Order.ItemName

nhibernate sessions

Entity Photos belongs to Property entity and one property can have many photos. Mapping is fine, creating data is doing ok. In db my photos are stored for example
Id 1 binarydata PropertyId(100)
And Property article with Id of 100 have reference to many photos. I'm write all this to say that my creation of data is ok and mapping as well.
So, the problem is on loading photo collection on showing property details.
I need to load photo collection inside session, so I'm stuck here.
public ActionResult Details(int id)
{
MyDomain.Property data = null;
using (//session)
{
using (//transaction)
{
data = session.QueryOver<MyDomain.Property>()
.Where(x => x.Id == id)
.Fetch(x => x.Photos).Eager //empty
.Fetch(x => x.Features).Eager
.SingleOrDefault<MyDomain.Property>();
//I was thinking here to call
// data.Photos = GetMyPhotos(id);
tx.Commit();
return PartialView("_HomePageDetailsPartial", data);
}
}
//return PartialView("_HomePageDetailsPartial", data);
}
As you can see in this I tried with data.Photos = GetMyPhotos(id); but on debug I have Error message Cannot update identity column 'Id'.Cannot update identity column 'Id'.
Even this work, I'm convinced that there is some more elegant way to retrieve photos collection for particular property.
My mappings
public class PhotoMap : ClassMap<Photo>
{
public PhotoMap()
{
Table("Photo");
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.ImageData).CustomSqlType("VARBINARY(MAX)").Length(160000).Not.Nullable();
Map(x => x.ImageMimeType).Not.Nullable();
References(x => x.Property).Column("PropertyId");
}
}
public class PropertyMap : ClassMap<Property>
{
public PropertyMap()
{
Table("Property");
Id(x => x.Id).GeneratedBy.Identity();
...
References(x => x.Features, "FeaturesId");
HasMany(x => x.Photos).KeyColumn("Id").Cascade.All();
}
}
DB snapshot
Two tables, Property and Photo.
Id int not null
Title nvarchar(255) not null
PhotoId int not null
Photo table
Id int not null
ImageData varbinary(MAX) null
ImageMimeType varchar(50) null
PropertyId int not null
Relationship is as follows:
FK_Property_Photo
Primary Key table Foreign key table
--------------------------------------------
Photo Property
--------------------------------------------
Id PhotoId
your KeyColumn in your mapping is wrong. KeyColumn is used to define the foreign key column in the n-table. In your case, the key column should be "PropertyId".
in addition: why do you have a PhotoId column in your property table if the relation between property and photo is 1:n?

Grails one-to-many mapping with joinTable

I have two domain-classes. One is a "Partner" the other is a "Customer". A customer can be a part of a Partner and a Partner can have 1 or more Customers:
class Customer {
Integer id
String name
static hasOne = [partner:Partner]
static mapping = {
partner joinTable:[name:'PartnerMap',column:'partner_id',key:'customer_id']
}
}
class Partner {
Integer id
static hasMany = [customers:Customer]
static mapping = {
customers joinTable:[name:'PartnerMap',column:'customer_id',key:'partner_id']
}
}
However, whenever I try to see if a customer is a part of a partner, like this:
def customers = Customer.list()
customers.each {
if (it.partner) {
println "Partner!"
}
}
I get the following error:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select this_.customer_id as customer1_162_0_, this_.company as company162_0_, this_.display_name as display3_162_0_, this_.parent_customer_id as parent4_162_0_, this_.partner_id as partner5_162_0_, this_.server_id as server6_162_0_, this_.status as status162_0_, this_.vertical_market as vertical8_162_0_ from Customer this_]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query
It looks as if Grails is thinking partner_id is a part of the Customer query, and it's not... It is in the PartnerMap table, which is supposed to find the customer_id, then get the Partner from the corresponding partner_id.
Anyone have any clue what I'm doing wrong?
Edit: I forgot to mention I'm doing this with legacy database tables. So I have a Partner, Customer and PartnerMap table. PartnerMap has simply a customer_id and partner_id field.
Given the way 1-many works when you want a join table, I think it's not possible with standard GORM to make it bidirectional and access a Customer's Partner. But you can map the join table with a domain class and access things that way:
Customer:
class Customer {
String name
def getPartner() {
PartnerMap.findByCustomer(this)?.partner
}
}
Partner:
class Partner {
String name
def getCustomers() {
PartnerMap.findAllByPartner(this)*.customer
}
}
PartnerMap:
import org.apache.commons.lang.builder.HashCodeBuilder
class PartnerMap implements Serializable {
Partner partner
Customer customer
boolean equals(other) {
if (!(other instanceof PartnerMap)) {
return false
}
other.partner?.id == partner?.id &&
other.customer?.id == customer?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (partner) builder.append(partner.id)
if (customer) builder.append(customer.id)
builder.toHashCode()
}
static PartnerMap get(long partnerId, long customerId) {
find 'from PartnerMap where partner.id=:partnerId and customer.id=:customerId',
[partnerId: partnerId, customerId: customerId]
}
static PartnerMap create(Partner partner, Customer customer, boolean flush = false) {
new PartnerMap(partner: partner, customer: customer).save(flush: flush, insert: true)
}
static boolean remove(Partner partner, Customer customer, boolean flush = false) {
PartnerMap instance = PartnerMap.findByPartnerAndCustomer(partner, customer)
instance ? instance.delete(flush: flush) : false
}
static void removeAll(Partner partner) {
executeUpdate 'DELETE FROM PartnerMap WHERE partner=:partner', [partner: partner]
}
static void removeAll(Customer customer) {
executeUpdate 'DELETE FROM PartnerMap WHERE customer=:customer', [customer: customer]
}
static mapping = {
id composite: ['customer', 'partner']
version false
table 'PartnerMap'
}
}
Since you're not using hasMany, you lose the addToXXX dynamic method, but you can call PartnerMap.create() to relate two instances. You also lose the collection and back-ref in the domain classes, but I added utility methods for those.

Resources