DataServieException: Oracle, EFOracleProvider, POCO and EF 4.0 - oracle

I try to use the new POCO capabilities of EF 4.0 in combination with the EFOracleProvider. I have recompiled the EFOracleProvider (using ODAC instead of System.Data.OracleClient) to target the .NET Framework 4 (und put it in the 4.0 GAC). Everything ok so far.
I host the Entity Model in a WCF Data Service:
class DivaDispoDataService : DataService<DivaDispoContainer>
{
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
}
My EDMX File looks like this:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="DivaDispo.Store" Alias="Self" Provider="EFOracleProvider" ProviderManifestToken="10g">
<EntityContainer Name="DivaDispoStoreContainer">
<EntitySet Name="DIW_USER" EntityType="DivaDispo.Store.DIW_USER" store:Type="Tables" Schema="" />
</EntityContainer>
<EntityType Name="DIW_USER">
<Key>
<PropertyRef Name="IDX" />
</Key>
<Property Name="IDX" Type="number" Nullable="false" Precision="10" />
<Property Name="USERNAME" Type="number" Precision="10" />
<Property Name="PERSONNELNUMBER" Type="number" Precision="10" />
<Property Name="PASSWORD" Type="varchar2" MaxLength="10" />
<Property Name="ACTIVATED" Type="number" Precision="1" />
<Property Name="ROLE" Type="number" Precision="1" />
</EntityType>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="DivaDispo.Model" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
<EntityContainer Name="DivaDispoContainer" annotation:LazyLoadingEnabled="false">
<EntitySet Name="User" EntityType="DivaDispo.Model.User" />
</EntityContainer>
<EntityType Name="User">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Decimal" Nullable="false" Precision="10" Scale="0" />
<Property Name="Username" Type="Decimal" Precision="10" Scale="0" />
<Property Name="PersonnelNumber" Type="Decimal" Precision="10" Scale="0" />
<Property Name="Password" Type="String" MaxLength="10" Unicode="false" FixedLength="false" />
<Property Name="Activated" Type="Boolean" />
<Property Name="Role" Type="Boolean" />
</EntityType>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs" Space="C-S">
<EntityContainerMapping StorageEntityContainer="DivaDispoStoreContainer" CdmEntityContainer="DivaDispoContainer">
<EntitySetMapping Name="User">
<EntityTypeMapping TypeName="IsTypeOf(DivaDispo.Model.User)">
<MappingFragment StoreEntitySet="DIW_USER">
<ScalarProperty Name="ID" ColumnName="IDX" />
<ScalarProperty Name="Username" ColumnName="USERNAME" />
<ScalarProperty Name="PersonnelNumber" ColumnName="PERSONNELNUMBER" />
<ScalarProperty Name="Password" ColumnName="PASSWORD" />
<ScalarProperty Name="Activated" ColumnName="ACTIVATED" />
<ScalarProperty Name="Role" ColumnName="ROLE" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
</edmx:Edmx>
My POCO Class looks like this:
public partial class User
{
public virtual decimal ID { get; set; }
public virtual Nullable<decimal> Username { get; set; }
public virtual Nullable<decimal> PersonnelNumber { get; set; }
public virtual string Password { get; set; }
public virtual Nullable<bool> Activated { get; set; }
public virtual Nullable<bool> Role { get; set; }
}
and the DataContext like this:
public partial class DivaDispoContainer : ObjectContext
{
public const string ConnectionString = "name=DivaDispoContainer";
public const string ContainerName = "DivaDispoContainer";
#region Constructors
public DivaDispoContainer()
: base(ConnectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = false;
}
public DivaDispoContainer(string connectionString)
: base(connectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = false;
}
public DivaDispoContainer(EntityConnection connection)
: base(connection, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = false;
}
#endregion
#region ObjectSet Properties
public ObjectSet<User> User
{
get { return _user ?? (_user = CreateObjectSet<User>("User")); }
}
private ObjectSet<User> _user;
}
The POCO classes and the DataContext are generated with the POCO Template from Visual Studio 2010.
When I start my WCF Service and want to query the users I receive an System.Data.Services.DataServiceException which says somtihng like
500: Internal Server error. The type 'System.Data.Entity.DynamicProxies.User_057822846B2B8DD7BB03058490B27D19E6C634EACF33438FE886 19C8BBB1CF74' is not a komplex type or entity type.
When I look in the dubgger I can see that the values have been read from the database (therefore I think the EFOracleProvider works ok) and that the DynamicProxies.User_.... is derrived from my User class (which contains at that point the data from the database). So the question is: Why do I receive this exception? Does anyone know whats going on there? What's the DynamicProxies.User_.... automaic generated class for? The Exception is thrown in the Method GetNonPrimitiveResourceType of the class WebUtil. Or maybe I have something overlooked?
Any help greatly appreciated....

The link from Craig to the blog post http://msdn.microsoft.com/en-us/library/ee705457.aspx revealed the answer. It states there that
The POCO proxy type cannot be directly serialized or deserialized by WCF
and that is exactly my problem. If I remove the virtual from the properties of the genrated POCO class the runtime doesnt generate the proxy types and the exception dissapears.
Thanks again for the link, Craig.

Related

REST Web API post related entities

Hi CodeFluent enthusiasts!
I have these two related entities in my model:
<cf:entity name="Main" defaultUsePersistenceDefaultValue="false" namespace="idscommerce" categoryPath="/idscommerce">
<cf:property name="Id" key="true" />
<cf:property name="Nom" />
<cf:property name="Ordre" />
<cf:property name="URL" />
<cf:property name="Icona" />
<cf:property name="Texts" typeName="{0}.MainTextCollection" relationPropertyName="Main" dataMember="true" />
<cf:entity name="MainText" defaultUsePersistenceDefaultValue="false" namespace="idscommerce" categoryPath="/idscommerce">
<cf:property name="Id" key="true" />
<cf:property name="Text" />
<cf:property name="Idioma" typeName="{0}.Idioma" relationPropertyName="MainTexts" />
<cf:property name="Main" typeName="{0}.Main" relationPropertyName="Texts" />
In my API, GET is working right, but when I POST (I'm using the [FromBody]Main value option) it goes into a loop at LoadByMain method from MainTextCollection.
// GET api/Main/id
public Main Get(string id)
{
idscommerce.Main value = idscommerce.Main.LoadByEntityKey(id);
if(value == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return value;
}
// POST api/Main
public HttpResponseMessage Post([FromBody]Main value)
{
if(value == null || !value.Save())
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
return Request.CreateResponse(HttpStatusCode.OK, value);
}
What it's weird is that the same class works as expected when calling from Main.LoadAll() or Main.LoadById(id), but it's going into an endless loop when called from the API POST method using Post([FromBody]Main value).

Navigation property values not added to entity

I've a WebAPI OData v3 (5.6.3) service (without EF) which I call from breeze using server side metadata. Unfortunately I cannot get navigation properties to load correctly in breeze.
The model is defined as following:
public class ParentItem
{
private readonly List<ChildItem> childItems = new List<ChildItem>();
[Key]
public int Id { get; set; }
public virtual ICollection<ChildItem> ChildItems
{
get
{
return this.childItems;
}
}
#endregion
}
public class ChildItem
{
[Key]
public int Id { get; set; }
[ForeignKey("ParentItem")]
public int? ParentItemId { get; set; }
public virtual ParentItem ParentItem { get; set; }
}
These are the metadata generated by the server:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<Schema Namespace="Solutions2Share.Solutions.MeetingManagerWeb.Models" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="ParentItem">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<NavigationProperty Name="ChildItems" Relationship="MyNamespace_ChildItem_ChildItemsPartner" ToRole="ChildItems" FromRole="ChildItemsPartner" />
</EntityType>
<EntityType Name="ChildItem">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="ParentId" Type="Edm.Int32" />
<NavigationProperty Name="ParentItem" Relationship="MyNamespace_ParentItem_ParentItemPartner" ToRole="ParentItem" FromRole="ParentItemPartner" />
</EntityType>
<Association Name="MyNamespace_ChildItem_ChildItemsPartner">
<End Type="MyNamespace.ChildItem" Role="ChildItems" Multiplicity="*" />
<End Type="MyNamespace.ParentItem" Role="ChildItemsPartner" Multiplicity="0..1" />
</Association>
<Association Name="MyNamespace_ParentItem_ParentItemPartner">
<End Type="MyNamespace.ParentItem" Role="ParentItem" Multiplicity="0..1" />
<End Type="MyNamespace.ChildItem" Role="ParentItemPartner" Multiplicity="0..1" />
</Association>
<EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
<EntitySet Name="ParentItems" EntityType="MyNamespace.ParentItem" />
<EntitySet Name="ChildItems" EntityType="MyNamespace.ChildItem" />
<AssociationSet Name="MyNamespace_ChildItem_ChildItemsPartnerSet" Association="MyNamespace_ChildItem_ChildItemsPartner">
<End Role="ChildItemsPartner" EntitySet="ParentItems" />
<End Role="ChildItems" EntitySet="ChildItems" />
</AssociationSet>
<AssociationSet Name="MyNamespace_ParentItem_ParentItemPartnerSet" Association="MyNamespace_ParentItem_ParentItemPartner">
<End Role="ParentItemPartner" EntitySet="ChildItems" />
<End Role="ParentItem" EntitySet="ChildItems" />
</AssociationSet>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
I'm using webApiOData on the client:
breeze.config.initializeAdapterInstance('dataService', 'webApiOData', true);
The query which I'm execute looks like this:
breeze.EntityQuery().from('ParentItems').expand('ChildItems');
The server call returns the correct items:
{
"odata.metadata":"http://example.com/api/$metadata#ParentItems","value":[
{
"odata.type":"MyNamespace.ParentItem","odata.id":"http://example.com/api/ParentItems(1)","ChildItems#odata.navigationLinkUrl":"http://example.com/api/ParentItems(1)/ChildItems","ChildItems":[
{
"odata.type":"MyNamespace.ChildItem","odata.id":"http://example.com/api/ChildItems(1)","ParentItem#odata.navigationLinkUrl":"http://example.com/api/ChildItems(1)/ParentItem","Id":1,"ParentItemId":1
},{
"odata.type":"MyNamespace.ChildItem","odata.id":"http://example.com/api/ChildItems(2)","ParentItem#odata.navigationLinkUrl":"http://example.com/api/ChildItems(2)/ParentItem","Id":2,"ParentItemId":1
}
],"Id":1
}
]
}
But the ChildItems property of the ParentItem entity is empty.
Edit: If I call manager.getEntities()after executing the query all parent and child items are returned.

how to get the string value and save it in database

I am using spring form tags and hibernate..
my jsp page has the follwoing code:
<tr><td><form:input path="userEnteredHostNameString" size="30" maxlength="200"/></td>
<td><form:input path="userEnteredDirectoryString" size="30" maxlength="200"/></td>
<td><form:input path="userEnteredUserNameString" size="20" maxlength="20"/></td>
<td><form:input path="userEnteredPasswordString" size="20" maxlength="20"/></td></tr>
getters and setters in my location.java
public String getUserEnteredHostNameString() {
return userEnteredHostNameString;
}
public void setUserEnteredHostNameString(String userEnteredHostNameString) {
if (userEnteredHostNameString!=null) userEnteredHostNameString = userEnteredHostNameString.toUpperCase();
this.userEnteredHostNameString = userEnteredHostNameString;
}
public String getUserEnteredDirectoryString() {
return userEnteredDirectoryString;
}
public void setUserEnteredDirectoryString(String userEnteredDirectoryString) {
if (userEnteredDirectoryString!=null) userEnteredDirectoryString = userEnteredDirectoryString.toUpperCase();
this.userEnteredDirectoryString = userEnteredDirectoryString;
}
public String getUserEnteredUserNameString() {
return userEnteredUserNameString;
}
public void setUserEnteredUserNameString(String userEnteredUserNameString) {
if (userEnteredUserNameString!=null) userEnteredUserNameString = userEnteredUserNameString.toUpperCase();
this.userEnteredUserNameString = userEnteredUserNameString;
}
public String getUserEnteredPasswordString() {
return userEnteredPasswordString;
}
public void setUserEnteredPasswordString(String userEnteredPasswordString) {
if (userEnteredPasswordString!=null) userEnteredPasswordString = userEnteredPasswordString.toUpperCase();
this.userEnteredPasswordString = userEnteredPasswordString;
}
In my controller, I have the following code:
FtpScanEvents f = new FtpScanEvents();
if(location.getUserEnteredHostNameString()!=null){
f.setHostName(location.getUserEnteredHostNameString());
}
if(location.getUserEnteredDirectoryString()!=null){
f.setDirectory(location.getUserEnteredDirectoryString());
}
if(location.getUserEnteredUserNameString()!=null){
f.setUserName(location.getUserEnteredUserNameString());
}
if(location.getUserEnteredPasswordString()!=null){
f.setPassword(location.getUserEnteredPasswordString());
}
ftpDao.save(f);
FtpScanEvents table has hostName, directory, username, password, locationId, idx, Id as columns..
hbm mapping file for ftpscanevents:
<hibernate-mapping package="ca.ups.tundra.model">
<class name="FtpScanEvents" table="FTP_SCAN_EVENTS">
<id name="id" type="long">
<generator class="native"/>
</id>
<property name="hostName" type="string" column="HOSTNAME" length="200"/>
<property name="directory" type="string" column="DIRECTORY" length="200"/>
<property name="userName" type="string" column="USERNAME" length="20"/>
<property name="password" type="string" column="PASSWORD" length="20"/>
<many-to-one name="location" class="Location" cascade="all">
<column name="ID" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
save(e entity) code..
#Override
#Transactional(propagation = Propagation.MANDATORY)
public void save(E entity) {
if(entity == null)
throw new NullArgumentException("entity");
Session s = sessionFactory.getCurrentSession();
s.saveOrUpdate(entity);
}
when it comes to ftpDao.save(f); program terminates and there are no errors in the console..any suggestion is greatly appreciated..
In the save method, I was missing a property. Added that property with a if condition and it worked!

Spring Security : How to rename the "_spring_security_remember_me" checkbox field?

In a Spring MVC 3.1 application I'm trying to implement a remember-me feature (with info saved in the database).
Here's what I currently have :
I created a persistent_logins table.
I have this in my security context file :
<form-login login-page="/login"
authentication-failure-url="/login?err=true"
default-target-url="/"
username-parameter="username"
password-parameter="password"
login-processing-url="/validatelogin" />
<remember-me key="some_random_key"
token-validity-seconds="31536000"
data-source-ref="dataSource" />
In my login.jsp, I have :
<form action="/validatelogin" method="post">
username : <input type='text' id='username' name='username' value='${SPRING_SECURITY_LAST_EXCEPTION.authentication.principal}' />
<br />
password : <input type='password' id='password' name='password' />
<br /><br />
remember me : <input type="checkbox" name="_spring_security_remember_me" />
<br /><br />
<input type="submit" value="submit" />
</form>
In the "<form-login>" bean, I've been able to rename the default "j_password" and "j_username" fields that have to be used in the jsp, using username-parameter and password-parameter. But I don't find a way to rename the "_spring_security_remember_me" checkbox field.
Any idea on how to rename it?
That is set using the parameter property of RememberMeServices.
Sadly this isn't settable using the namespace config. Here are a couple of ways you could set it:
Create a custom RememberMeServices and use it using <remember-me services-ref="myRememberMeServices">. Set the property on your bean.
Use a BeanPostProcessor (see 1.8) to set the property on the default RememberMeServices.
You should use BeanPostProcessor to set correct property:
Let's consider that you want to call your property "myRememberMeProperty"
Then your code should look like this:
public class MyBeanPostProcessor implements BeanPostProcessor {
String myRememberMeProperty;
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof AbstractRememberMeServices) {
AbstractRememberMeServices rememberMe = (AbstractRememberMeServices) bean;
rememberMe.setParameter(getMyRememberMeProperty());
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String name) {
return bean;
}
public void setMyRememberMeProperty(String myRememberMeProperty){
this.myRememberMeProperty = myRememberMeProperty;
}
public String getMyRememberMeProperty(){
return this.myRememberMeProperty;
}
}
<bean id="myBeanPostProcessor"
class="x.y.z.MyBeanPostProcessor">
<property name="myRememberMeProperty" value="myRememberMeProperty" />
</bean>
Hope it helps.

How to start myBatis implemention with spring?

I want to work with myBatis. I have read MyBatis-3-user-guide. Now i am trying to implement it. Recently i have learned spring. So it is difficult for me to implement it. So i need some helpful resource by which i can implement it step by step.
Add the MyBatis-Spring jar in your class path at first
Start with your spring context file.In your context file add following lines
<beans:bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="yourDriverClassName"
p:url="yourUrl"
p:username="yourUsername"
p:password="yourPassword" />
<beans:bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="configLocation" value="/WEB-INF/mybatis-config.xml" />
</beans:bean>
<beans:bean id="userDao" class="com.yourcomp.dao.Userdao">
<beans:property name="sqlSessionFactory" ref="sqlSessionFactory" />
</beans:bean>
your mybatis-config.xml should be something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
</settings>
<typeAliases>
<typeAlias alias="User" type ="com.yourcomp.domain.User" />
</typeAliases>
<mappers>
<mapper resource="com/yourcomp/domain/UserMapper.xml"/>
<mapper resource="com/yourcomp/domain/AnotherDomainObjectMapper.xml"/>
</mappers>
</configuration>
and your userMapper.xml in src/com/yourcomp/domain/ might be something like this
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--<mapper namespace="org.pbl.rms.RMSUserDao">-->
<mapper namespace="com.yourcomp.domain.User">
<resultMap id="userMap" type="User">
<id property="userId" column="USER_ID" javaType="int" jdbcType="NUMERIC"/>
<result property="userName" column="USER_NAME" javaType="String" jdbcType="VARCHAR"/>
<result property="userFullName" column="USER_FULL_NAME" javaType="String" jdbcType="VARCHAR"/>
<result property="password" column="PASSWORD" javaType="String" jdbcType="VARCHAR"/>
<result property="passwordExpiryDate" column="PASWRD_EXPIRY_DATE" javaType="java.util.Date" jdbcType="DATE"/>
<result property="status" column="STATUS" javaType="_integer" jdbcType="DECIMAL"/>
</resultMap>
<select id="getUserById" parameterType="map" resultMap="userMap">
select * from user where USER_ID=#{userId}
</select>
</mapper>
now in your DAO layer you might have class like follows:
public class UserDAO{
private SqlSessionFactory sqlSessionFactory;
public UserDAO() {
}
public UserDAO(SqlSessionFactory sqlSessionFactory ) {
this.sqlSessionFactory = sqlSessionFactory;
}
public String getUserById(Integer userId) {
SqlSession session = sqlSessionFactory.openSession();
String name=null;
try {
name = (String)session.selectOne("com.yourcomp.domain.User.getUserById",userId);
}catch(Exception e){
}finally {
session.close();
}
return name;
}
}
You need MyBatis-Spring for this . See the reference here and here These provide you the step by step configs . If you need any specific details , you need to re frame your query .
Also check the spring reference for IBatis support.

Resources