Two distinct associations instead of one - entity-framework

I have two related entities (I've added all possible data annotations, but it seems that ODataConventionModelBuilder ignores them):
public class Examination
{
[InverseProperty("Examination")]
public virtual ICollection<Variable> Variables { get; set; }
}
public abstract class Variable
{
[Required]
public int? ExaminationId { get; set; }
[Required]
[ForeignKey("ExaminationId")]
[InverseProperty("Variables")]
public virtual Examination Examination { get; set; }
}
Here is an OData model generation (it seems, that HasMany() and HasRequired() doesn't affect resulting model):
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Examination>("Examinations");
modelBuilder.EntitySet<Variable>("Variables");
modelBuilder.Entity<Examination>().HasMany(e => e.Variables);
modelBuilder.Entity<Variable>().HasRequired(v => v.Examination);
return modelBuilder.GetEdmModel();
Resulting model:
<EntityType Name="Examination">
<NavigationProperty Name="Variables" Relationship="YoStat.Models.YoStat_Models_Examination_Variables_YoStat_Models_Variable_VariablesPartner" ToRole="Variables" FromRole="VariablesPartner"/>
</EntityType>
<EntityType Name="Variable" Abstract="true">
<NavigationProperty Name="Examination" Relationship="YoStat.Models.YoStat_Models_Variable_Examination_YoStat_Models_Examination_ExaminationPartner" ToRole="Examination" FromRole="ExaminationPartner"/>
</EntityType>
<Association Name="YoStat_Models_Examination_Variables_YoStat_Models_Variable_VariablesPartner">
<End Type="YoStat.Models.Variable" Role="Variables" Multiplicity="*"/>
<End Type="YoStat.Models.Examination" Role="VariablesPartner" Multiplicity="0..1"/>
</Association>
<Association Name="YoStat_Models_Variable_Examination_YoStat_Models_Examination_ExaminationPartner">
<End Type="YoStat.Models.Examination" Role="Examination" Multiplicity="1"/>
<End Type="YoStat.Models.Variable" Role="ExaminationPartner" Multiplicity="0..1"/>
</Association>
<EntityContainer Name="Container">
<EntitySet Name="Examinations" EntityType="YoStat.Models.Examination"/>
<EntitySet Name="Variables" EntityType="YoStat.Models.Variable"/>
<AssociationSet Name="YoStat_Models_Examination_Variables_YoStat_Models_Variable_VariablesPartnerSet" Association="YoStat.Models.YoStat_Models_Examination_Variables_YoStat_Models_Variable_VariablesPartner">
<End Role="VariablesPartner" EntitySet="Examinations"/>
<End Role="Variables" EntitySet="Variables"/>
</AssociationSet>
<AssociationSet Name="YoStat_Models_Variable_Examination_YoStat_Models_Examination_ExaminationPartnerSet" Association="YoStat.Models.YoStat_Models_Variable_Examination_YoStat_Models_Examination_ExaminationPartner">
<End Role="ExaminationPartner" EntitySet="Variables"/>
<End Role="Examination" EntitySet="Examinations"/>
</AssociationSet>
</EntityContainer>
As you can see, it generates two distinct associations instead of one. How to fix it? Thanks!

This looks like a bug in odata model builder, which always creates unidirectional navigation for each navigation property, while the better way is to look into the model to check if it's a bidirectional navigation first. I filed the bug at: http://aspnetwebstack.codeplex.com/workitem/623
However, I didn't find anything broken in client side with current behavior. WCF DS client will still generate correct proxy classes. Do you have any specific user scenario which is blocked by it? The information will help the bug to be better triaged. Thanks.

Related

Hibernate Search query searches all tables instead of only the specified class' table

I have an abstract class Product that are subclassed by ProductA, ProductB and ProductC.
And the classes ProductA, ProductB and ProductC are mapped to the database tables PRODUCTS_A, PRODUCTS_B and PRODUCTS_C respectively.
Now I want to perform a full-text search on ProductA entities by Hibernate Search.
I wrote some code to successfully get expected ProductA entities from database, but I found in the log (as follows) that the executed Hibernate Search query actually searched all the tables PRODUCTS_A, PRODUCTS_B and PRODUCTS_C instead of only the table PRODUCTS_A I expected.
I want to get only ProductA entities, why are ProductB and PRODUCTS_C tables also searched? Is there a way to fix this?
Log
You can see from the following working log outputted by Hibernate that besides the PRODUCTS_A table, the PRODUCTS_B and PRODUCTS_C tables are also searched.
Hibernate: select this_.ID as ID1_2_0_, this_.NAME as NAME2_2_0_, this_.FEATURE as FEATURE3_2_0_, this_.CREATED_DATE as CREATED_4_2_0_, this_.MODIFIED_DATE as MODIFIED5_2_0_, this_.FEATURE_A1 as FEATURE_1_3_0_, this_.FEATURE_A2 as FEATURE_2_3_0_, this_.FEATURE_B1 as FEATURE_1_4_0_, this_.FEATURE_B2 as FEATURE_2_4_0_, this_.FEATURE_C1 as FEATURE_1_5_0_, this_.FEATURE_C2 as FEATURE_2_5_0_, this_.clazz_ as clazz_0_ from ( select ID, NAME, FEATURE, CREATED_DATE, MODIFIED_DATE, FEATURE_A1, FEATURE_A2, null::varchar as FEATURE_B1, null::varchar as FEATURE_B2, null::varchar as FEATURE_C1, null::varchar as FEATURE_C2, 1 as clazz_ from PRODUCTS_A union all select ID, NAME, FEATURE, CREATED_DATE, MODIFIED_DATE, null::varchar as FEATURE_A1, null::varchar as FEATURE_A2, FEATURE_B1, FEATURE_B2, null::varchar as FEATURE_C1, null::varchar as FEATURE_C2, 2 as clazz_ from PRODUCTS_B union all select ID, NAME, FEATURE, CREATED_DATE, MODIFIED_DATE, null::varchar as FEATURE_A1, null::varchar as FEATURE_A2, null::varchar as FEATURE_B1, null::varchar as FEATURE_B2, FEATURE_C1, FEATURE_C2, 3 as clazz_ from PRODUCTS_C ) this_ where (this_.ID in (?))
Code
Entity Classes
Here are the entity classes Product, ProductA, ProductB and ProductC.
public abstract class Product {
#Id
protected Long id;
#Field
protected String name;
#Field
protected String feature;
protected Date createdDate;
protected Date modifiedDate;
// Getters and setters...
}
#Entity
#Indexed
public class ProductA extends Product {
#Field
private String featureA1;
#Field
private String featureA2;
public ProductA() {
}
// Getters and setters...
}
The ProductB and ProductC classes are similar as the ProductA class.
Hibernate Mapping File
Product.hbm.xml
The union-subclass element is used to reflect the subclass relationship between the Product class and the ProductA, ProductB and ProductC classes.
<hibernate-mapping package="com.raychen518.study.hibernate">
<class name="Product" abstract="true">
<id name="id" column="ID">
<generator class="increment" />
</id>
<property name="name" column="NAME" />
<property name="feature" column="FEATURE" />
<property name="createdDate" type="timestamp" column="CREATED_DATE" />
<property name="modifiedDate" type="timestamp" column="MODIFIED_DATE" />
<union-subclass name="ProductA" table="PRODUCTS_A">
<property name="featureA1" column="FEATURE_A1" />
<property name="featureA2" column="FEATURE_A2" />
</union-subclass>
<union-subclass name="ProductB" table="PRODUCTS_B">
<property name="featureB1" column="FEATURE_B1" />
<property name="featureB2" column="FEATURE_B2" />
</union-subclass>
<union-subclass name="ProductC" table="PRODUCTS_C">
<property name="featureC1" column="FEATURE_C1" />
<property name="featureC2" column="FEATURE_C2" />
</union-subclass>
</class>
</hibernate-mapping>
Hibernate Configuration File
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost:5432/test</property>
<property name="connection.username">postgres</property>
<property name="connection.password">admin</property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">validate</property>
<!-- Setting for Hibernate Search -->
<property name="hibernate.search.lucene_version">LUCENE_CURRENT</property>
<property name="hibernate.search.default.directory_provider">filesystem</property>
<property name="hibernate.search.default.indexBase">hibernate.search.test/lucene/indexes</property>
<mapping resource="Product.hbm.xml" />
</session-factory>
</hibernate-configuration>
Application Launcher Class
The ProductManager class contains the main method, thus serves as the application launcher. It starts the Hibernate Search indexing process, clears the PRODUCTS_A, PRODUCTS_B and PRODUCTS_C tables and inserts some sample product data into them, and finally performs a full-text search using the Hibernate Search.
What confuses me is that I have specified the target entity as ProductA.class in the following statement Query query = fullTextSession.createFullTextQuery(luceneQuery, ProductA.class); in the method searchProducts(). Why does Hibernate Search also search ProductB and ProductC entities?
public class ProductManager {
public static void main(String[] args) throws InterruptedException {
ProductManager productManager = new ProductManager();
productManager.indexAllProducts();
productManager.deleteAllProducts();
productManager.generateSomeProducts();
productManager.searchProducts();
}
private void indexAllProducts() throws InterruptedException {
FullTextSession fullTextSession = Search.getFullTextSession(HibernateUtil.getSessionFactory().getCurrentSession());
fullTextSession.createIndexer().startAndWait();
}
public void deleteAllProducts() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
#SuppressWarnings("unchecked")
List<Product> results = session.createQuery("from Product").list();
for (Product result : results) {
session.delete(result);
}
session.getTransaction().commit();
}
public void generateSomeProducts() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(new ProductA("feature001", "featureA1001", "featureA2001", new Date()));
session.save(new ProductA("feature002", "featureA1002", "featureA2002", new Date()));
session.save(new ProductA("feature003", "featureA1003", "featureA2003", new Date()));
session.save(new ProductB("feature001", "featureB1001", "featureB2001", new Date()));
session.save(new ProductB("feature002", "featureB1002", "featureB2002", new Date()));
session.save(new ProductB("feature003", "featureB1003", "featureB2003", new Date()));
session.save(new ProductC("feature001", "featureC1001", "featureC2001", new Date()));
session.save(new ProductC("feature002", "featureC1002", "featureC2002", new Date()));
session.save(new ProductC("feature003", "featureC1003", "featureC2003", new Date()));
session.getTransaction().commit();
}
private void searchProducts() {
FullTextSession fullTextSession = Search.getFullTextSession(HibernateUtil.getSessionFactory().getCurrentSession());
fullTextSession.beginTransaction();
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(ProductA.class).get();
org.apache.lucene.search.Query luceneQuery = queryBuilder.keyword().onFields("feature").matching("feature002").createQuery();
// Set the 2nd method parameter using "Product.class" to get products of the types ProductA, ProductB and ProductC.
// Set the 2nd method parameter using "ProductA.class" to get products of the types ProductA.
Query query = fullTextSession.createFullTextQuery(luceneQuery, ProductA.class);
#SuppressWarnings("unchecked")
List<Product> queryResults = query.list();
for (Product queryResult : queryResults) {
System.out.println("queryResult: " + queryResult);
}
fullTextSession.getTransaction().commit();
}
}
I fixed it recently as https://hibernate.atlassian.net/browse/HSEARCH-2301 following another Stackoverflow question.
It hasn't been released yet but the patch is rather small and localized in only one file: https://github.com/hibernate/hibernate-search/pull/1122/files so you should be able to apply it locally on the 5.5 branch.
Use https://patch-diff.githubusercontent.com/raw/hibernate/hibernate-search/pull/1122.diff to get the raw diff file.
UPDATE we fixed it in 5.5.4.Final: http://in.relation.to/2016/06/29/Polishing-Polishing-And-More-Polishing-Hibernate-Search-5-5-4-Final/

Setting ConnectionTimeout when using EntityFramework

I would like to set the ConnectionTimeout to something other than the default, which is 15 seconds. I have inherited some code that uses EntityFramework and the app.config looks like this:
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS; Integrated Security=True; ConnectionTimeout=30; MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value="Data Source=.\SQLEXPRESS; Integrated Security=True; ConnectionTimeout=30; MultipleActiveResultSets=True" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
I'm the one who added the sectino in an attempt to get things working. I can tell it's not working be setting a breakpoint at:
var adapter = (IObjectContextAdapter) this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = CommandTimeoutSeconds;
int test = objectContext.Connection.ConnectionTimeout;
test is always 15. What is going on? Can someone tell me how to set ConnectionTimeout? I have tried both "ConnectionTimeout" and "Connection Timeout" I.e. no space vs. space.
Can someone help me? I'm pulling my hair out. I'm sure it's a simple fix!
Dave
Additional info. In response to comment, here is my DbContext derived class...
public class SessionDataContext : DbContext
{
// Command timeout (seconds)
private const int CommandTimeoutSeconds = 30;
/// <summary>
/// Constructor that takes db name.
/// The connection string and db itself is configured in the this project's app.config file
/// </summary>
/// <param name="dbName"></param>
public SessionDataContext(string dbName) : base(dbName)
{
Database.SetInitializer(new SessionDataContextInitializer());
// Set timeout (based on code from http://stackoverflow.com/questions/6232633/entity-framework-timeouts)
var adapter = (IObjectContextAdapter) this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = CommandTimeoutSeconds;
int test = objectContext.Connection.ConnectionTimeout;
}
/// <summary>
/// Session table's records
/// </summary>
public DbSet<Session> Sessions { get; set; }
/// <summary>
/// SessionType table's records
/// </summary>
public DbSet<SessionType> SessionTypes { get; set; }
}
It was stupidity on my part that was causing the problem! I put my answer here in case anyone in the future has this problem. Everything I typed above is correct and will work fine. However, the app.config file I was looking at was in a class library (our DataAccess layer). In fact, it was not being used at all and default EntityFramework settings were being used. I'm mot sure what led me to try it, but I moved the app.config settings from the DataAccess layer app.config to the main app.config and all worked beautifully. About all I can say in my defense other than I inherited the code is that it's not clear to me to see that the values in the app.config are not being used and one does not call them or use them in one's own code. Rather, MultipleActiveResultSets and ConnectionTimeout are used by the underlying Entity Framework.

Getting Data from Multiple tables in Liferay 6.0.6

i'm trying to get data from multiple tables in liferay 6.0.6 using custom sql, but for now i'm just able to display data from one table.does any one know how to do that.thanks
UPDATE:
i did found this link http://www.liferaysavvy.com/2013/02/getting-data-from-multiple-tables-in.html but for me it's not working because it gives an error BeanLocator is null,and it seems that it's a bug in liferay 6.0.6
The following technique also works with liferay 6.2-ga1.
We will consider we are in the portlet project fooproject.
Let's say you have two tables: article, and author. Here are the entities in your service.xml :
<entity name="Article" local-service="true">
<column name="id_article" type="long" primary="true" />
<column name="id_author" type="long" />
<column name="title" type="String" />
<column name="content" type="String" />
<column name="writing_date" type="Date" />
</entity>
<entity name="Author" local-service="true">
<column name="id_author" type="long" primary="true" />
<column name="full_name" type="String" />
</entity>
At that point run the service builder to generate the persistence and service layers.
You have to use custom SQL queries as described by Liferay's Documentation to fetch info from multiple databases.
Here is the code of your fooproject-portlet/src/main/ressources/default.xml :
<?xml version="1.0"?>
<custom-sql>
<sql file="custom-sql/full_article.xml" />
</custom-sql>
And the custom request in the fooproject-portlet/src/main/ressources/full_article.xml:
<?xml version="1.0"?>
<custom-sql>
<sql
id="com.myCompany.fooproject.service.persistence.ArticleFinder.findByAuthor">
<![CDATA[
SELECT
Author.full_name AS author_name
Article.title AS article_title,
Article.content AS article_content
Article.writing_date AS writing_date
FROM
fooproject_Article AS Article
INNER JOIN
fooproject_Author AS Author
ON Article.id_author=Author.id_author
WHERE
author_name LIKE ?
]]>
</sql>
</custom-sql>
As you can see, we want to fetch author's name, article's title, article's content and article's date.
So let's allow the service builder to generate a bean that can store all these informations. How ? By adding it to the service.xml ! Be careful: the fields of the bean and the fields' name returned by the query must match.
<entity name="ArticleBean">
<column name="author_name" type="String" primary="true" />
<column name="article_title" type="String" primary="true" />
<column name="article_content" type="String" />
<column name="article_date" type="Date" />
</entity>
Note: defining which field is primary here does not really matter as there will never be anything in the ArticleBean table. It is all about not having exceptions thrown by the service builder while generating the Bean.
The finder method must be implemented then. To do so, create the class com.myCompany.fooproject.service.persistence.impl.ArticleFinderImpl. Populate it with the following content:
public class ArticleFinderImpl extends BasePersistenceImpl<Article> {
}
Use the correct import statements and run the service builder. Let's make that class implement the interface generated by the service builder:
public class ArticleFinderImpl extends BasePersistenceImpl<Article> implements ArticleFinder {
}
And populate it with the actual finder implementation:
public class ArticleFinderImpl extends BasePersistenceImpl<Article> implements ArticleFinder {
// Query id according to liferay's query naming convention
public static final String FIND_BY_AUTHOR = ArticleFinder.class.getName() + ".findByAuthor";
public List<Article> findByAuthor(String author) {
Session session = null;
try {
session = openSession();
// Retrieve query
String sql = CustomSQLUtil.get(FIND_BY_AUTHOR);
SQLQuery q = session.createSQLQuery(sql);
q.setCacheable(false);
// Set the expected output type
q.addEntity("StaffBean", StaffBeanImpl.class);
// Binding arguments to query
QueryPos qpos = QueryPos.getInstance(q);
qpos.add(author);
// Fetching all elements and returning them as a list
return (List<StaffBean>) QueryUtil.list(q, getDialect(), QueryUtil.ALL_POS, QueryUtil.ALL_POS);
} catch(Exception e) {
e.printStackTrace();
} finally {
closeSession(session);
}
return null;
}
}
You can then call this method from your ArticleServiceImpl, whether it is to make a local or a remote API.
Note: it is hack. This is not a perfectly clean way to retrieve data, but it is the "less bad" you can do if you want to use Liferay's Service Builder.

Entity Framework + Repository Pattern and foreign key update not updating related entity

I'm using Entity Framework 5 and the UnitOfWork + Repository pattern.
I am trying to create the following entity:
public partial class ViaggioAttivita
{
public System.Guid Id { get; set; }
public System.Guid IdViaggio { get; set; }
public virtual Viaggio Viaggio { get; set; }
}
public partial class Viaggio
{
public System.Guid Id { get; set; }
public virtual ICollection<ViaggioAttivita> ViaggiAttivita { get; set; }
}
I noticed that when i create the new ViaggioAttivita entity populating the IdViaggio, when i do
ViaggioAttivita attivita = new ViaggioAttivita();
attivita.IdViaggio = ParentId;
unitOfWork.ViaggiAttivitaRepository.Insert(attivita);
the navigation property attivita.Viaggio does not get updated.
If I directly update the attivita.Viaggio instead of the Id
ViaggioAttivita attivita = new ViaggioAttivita();
attivita.Viaggio = unitOfWork.ViaggiRepository.GetByID(ParentId);
unitOfWork.ViaggiAttivitaRepository.Insert(attivita);
The Viaggio of course get updated, but the IdViaggio key gets updated too.
What am I missing ?
Why am I getting this difference?
I tried calling a .Save() but nothing changes.
It seems that relations only get updated if I manually update the entity, but they don't get updated if I update the key only.
Thank you
Edit 1:
I'm on Sql Server 2008, MVC3, Entity Framework 5 (runtime v4.0.30319 of course). Database First mode. The two tables have the relationship (of course, otherwise it would not populate the Key using the second method).
Edit 2:
I try to past some EDMX information;
<EntityType Name="Viaggio">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Guid" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
<NavigationProperty Name="ViaggiAttivita" Relationship="DatabaseModel.FK_ViaggiAttivita_Viaggi" FromRole="Viaggi" ToRole="ViaggiAttivita" />
</EntityType>
<EntityType Name="ViaggioAttivita">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Guid" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
<Property Name="IdViaggio" Type="Guid" Nullable="false" />
<NavigationProperty Name="Viaggio" Relationship="DatabaseModel.FK_ViaggiAttivita_Viaggi" FromRole="ViaggiAttivita" ToRole="Viaggi" />
</EntityType>
<AssociationSet Name="FK_ViaggiAttivita_Viaggi" Association="DatabaseModel.FK_ViaggiAttivita_Viaggi">
<End Role="Viaggi" EntitySet="Viaggi" />
<End Role="ViaggiAttivita" EntitySet="ViaggiAttivita" />
</AssociationSet>
The difference is:
a) Set Foreign Key Only. (Id) If this Entity is in loaded in the cache the Navigation property can be set. If it isnt loaded, then you would need to trigger the loading. You can search on how to or when this is done automatically. See topic lazy loading versus .include
b) Set navigation property with an entity.
the navigation property is supported by Foreign key Id field.
Now EF can see the Nav property and Its key. It can set the ID with data it already has. No need to load from DB. SO it is set.

Entity Framework 4 - Navigation Property Object Null on Client Side

There are two tables of interest in my entity conceptual model: tblProducts and tblInstalledProducts.
Each installed product has a ProductID foreign key linking it to a specific product, which was set up automatically as a navigation property.
Within the entity domain service I have the following query:
public IQueryable<tblInstalledProduct> GetInstalledProductsBySiteID(string SiteID)
{
ObjectSet<tblInstalledProduct> installedProducts = this.ObjectContext.tblInstalledProducts;
var filterBySite =
from p in installedProducts.Include("tblProduct")
where p.SiteID == SiteID
select p;
return filterBySite;
}
I have a DataGridView bound to a DomainDataSource configured to use this query.
When I debug this query, p.tblProduct and p.tblProductReference are populated as expected. The problem arises when trying to access the tblProduct property of any tblInstalledProduct from the client side.
//Find associated install record for the selected product
tblInstalledProduct selectedInstall =
Context.tblInstalledProducts.Where(
p => p.SiteID == "Site1" && p.ProductID == 38
).First();
string productName = selectedInstall.tblProduct.ProductName;
For some reason tblProduct is always null. I've tried .Include() / .Load() and can't seem to get it to populate itself.
Why is tblInstalledProduct.tblProduct loaded up as expected on the service side of things, but is seemingly inaccessible on the client side?
Thanks for reading.
Edit:
XAML DataSource:
<telerik:RadDomainDataSource x:Key="InstalledProductsDataSource"
Name="InstalledProductsDataSource"
DomainContext="{StaticResource DomainContext}"
AutoLoad="True"
QueryName="GetInstalledProductsInfoBySiteID"
SubmittedChanges="InstalledProductsDataSource_SubmittedChanges">
<telerik:RadDomainDataSource.QueryParameters>
<telerik:QueryParameter
ParameterName="SiteID"
Value="{Binding SelectedValue,ElementName=SiteList}" />
</telerik:RadDomainDataSource.QueryParameters>
</telerik:RadDomainDataSource>
XAML DataGrid:
<telerik:RadGridView x:Name="InstalledProductsGridView"
ItemsSource="{Binding DataView, Source={StaticResource InstalledProductsDataSource}}">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn Header="Product Name" DataMemberBinding="{Binding ProductName, Mode=TwoWay}" />
<telerik:GridViewDataColumn Header="Version" DataMemberBinding="{Binding ProductVersion, Mode=TwoWay}" />
<telerik:GridViewDataColumn Header="Description" DataMemberBinding="{Binding Description, Mode=TwoWay}" />
</telerik:RadGridView.Columns>
</telerik:RadGridView>
Right now the grid is bound to a collection of tblProducts, but I'd like to bind it to a collection of tblInstalledProducts (as there is some extra information in that table that I need access to) like so:
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn Header="DateInstalled" DataMemberBinding="{Binding DateInstalled, Mode=TwoWay}" />
<telerik:GridViewDataColumn Header="Product Name" DataMemberBinding="{Binding tblProduct.ProductName, Mode=TwoWay}" />
<telerik:GridViewDataColumn Header="Version" DataMemberBinding="{Binding tblProduct.ProductVersion, Mode=TwoWay}" />
<telerik:GridViewDataColumn Header="Description" DataMemberBinding="{Binding tblProduct.Description, Mode=TwoWay}" />
</telerik:RadGridView.Columns>
you need to do something like this
tblInstalledProduct selectedInstall = Context.GetInstalledProductsBySiteID("Site1").Where(p=> p.ProductID == 38 ).FirstOrDefault();
string productName="";
if(selectedInstall !=null)
{
productName= selectedInstall.tblProduct.ProductName;
}
for testing try to use;
public IQueryable<tblInstalledProduct> GetInstalledProductsNew()
{
//Im nut Sure of 'tblProduct' or 'tblProducts' it is dependent on your relations
return this.ObjectContext.tblInstalledProducts.Include("tblProduct");
}
For anyone else having problems with this, I did eventually find the solution. You need to use both .Include() on the query to tell it to load related objects, as well as the [Include] attribute in the metadata to allow those related objects to be serialized and sent to the client.