Mapping exception thrown by NHibernate - asp.net-mvc

I have the following models:
WeatherForecast:
namespace TravelAssistant.Model.HelperModels.Weather
public class WeatherForecast:EntityBase<int>
{
public IList<DayForecast> ForecastDays { get; set; }
public LocationBase ForecastLocation { get; set; }
public void Init(Location.LocationBase location)
{
this.ForecastLocation = location;
}
protected override void Validate()
{
throw new NotImplementedException();
}
}
LocationBase:
namespace TravelAssistant.Model.HelperModels.Location
public class LocationBase:EntityBase<int>
{
public string WorldRegion { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Zipcode { get; set; }
public string StreetNameNumber { get; set; }
}
where EntityBase defines an id of type T, and the following .hbm files
WeatherForecast.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="TravelAssistant.Model.HelperModels.Weather"
assembly="TravelAssistant.Model">
<class name="WeatherForecast" table="WeatherForecasts" lazy="false" >
<id name="Id" column="WeatherForecastID"
type="int" unsaved-value="0">
<generator class="native" />
</id>
<many-to-one name="ForecastLocation"
cascade="all"
class="LocationBase"
column="LocationID"
not-null="false" />
<bag name="ForecastDays" lazy="false" >
<key column="WeatherForecastID"/>
<one-to-many class="DayForecast"></one-to-many>
</bag>
</class>
</hibernate-mapping>
LocationBase.hbm.xml
<id name="Id" column="LocationID" type="int" unsaved-value="0">
<generator class="native" />
</id>
<property name="City">
<column name="City"
sql-type="varchar(150)" not-null="true" />
</property>
<property name="Country">
<column name="Country"
sql-type="varchar(50)" not-null="true" />
</property>
<property name="Zipcode">
<column name="Zipcode"
sql-type="varchar(50)" not-null="false" />
</property>
<property name="StreetNameNumber">
<column name="StreetNameNumber"
sql-type="varchar(150)" not-null="false" />
</property>
<property name="WorldRegion">
<column name="WorldRegion"
sql-type="varchar(100)" not-null="false" />
</property>
</class>
</hibernate-mapping>
The database model is:
WeatherForecasts : WeatherForecastID, LocationID
Locations:LocationID,City,Country,Zipcode, StreetNameNumber,WorldRegion.
When I run the program I get:
An association from the table WeatherForecasts refers to an unmapped class:
TravelAssistant.Model.HelperModels.Weather.LocationBase
Can someone point me where I got it wrong?

Try using the fully qualified class name for the many-to-one association on the WeatherForecast mapping.
<many-to-one
name="ForecastLocation"
cascade="all"
class="TravelAssistant.Model.HelperModels.Location.LocationBase, TravelAssistant.Model"
column="LocationID"
not-null="false" />

Related

OData: How to convert a System.Uri to Edm.String?

I'm building an OData Web API using ASPNetCore. The EdmModel is build like
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<MyType>("MyType");
edmModel = builder.GetEdmModel();
This is MyType
public class MyType
{
[Key]
public string Id { get; set; }
[Required]
public Uri Uri { get; set; }
}
This generates an EdmModel like this
<Schema Namespace="Test" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="MyType">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Uri" Type="System.Uri" Nullable="false" />
</EntityType>
</Schema>
<Schema Namespace="System" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<ComplexType Name="Uri">
<Property Name="Segments" Type="Collection(Edm.String)" />
</ComplexType>
</Schema>
When I query the OData controller I'm getting this response
{
"#odata.context": "https://localhost:44389/v3/$metadata#MyType/$entity",
"Id": "ID-1234",
"Uri": {
"Segments": [
"/",
"path/",
"to/",
"document"
]
}
}
That's not at all what I want.
How can I get this to return me the complete URI as a string?
Is there an attribute I need to add to the model, or is there a way to configure the builder differently?

arraylist(javaObect) iteration in velocity template

I have two tables Author, Books. And POJOs, .hbm.xml for each of the tables. I wrote a select query which gives me some details from both the tables.
select A.id.BookNum,A.id.AuthorName,B.id.DatePublished,B.id.Price
,B.id.Condition,B.id.BookBought from Author A, Book B where
B.id.Condition == 'NEW' and A.id.BookNum = A.id.BookNum order by
A.id.AuthorName;
I have got the results, and having it stored in ArrayList. UnApprovedBookList When i try to display this in velocity template i am not able to iterate this. I have my POJOs as Author, Book which has getter()/ Setter() for AuthorId and BookId respectively and AuthorId, BookId which has the getters/ setters for fields in it.
public class Book implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private BookId id;
public Book (){ }
public Book (BookId id){this.id = id;}
public BookId getId(){return id;}
public void setId(BookId id) {this.id = id;}
}
and my BookId with getters/ setters for the fields in it, basically all the table columns.
public class BookId implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private BookNum;
public BookId (){ }
public String getBookNumid() {return BookNum;}
public void setBookNum(String bookNum) {bookNum= bookNum;}
}
And my hbm as below:
<hibernate-mapping>
<class name="com.bookStore.hibernate.dao.Book" table="BOOK" schema="ORG">
<composite-id name="id" class="com.bookStore.hibernate.dao.BookId">
<key-property name="BookNum" type="string">
<column name="SH_BOOK_NUM" length="17" />
</key-property>
<key-property name="DatePublished" type="date">
<column name="SH_DATE_PUB" length="13" />
</key-property>
<key-property name="Price" type="int">
<column name="SH_PRICE" length="5" />
</key-property>
<key-property name="Condition" type="string">
<column name="SH_CONDITION" length="10" />
</key-property>
<key-property name="BookBought " type="date">
<column name="SH_BOOK_BOUGHT" length="13" />
</key-property>
</composite-id>
</class>
</hibernate-mapping>
And I am finding it difficult when I try to iterate and display in Velocity. my code snippet as below:
#foreach($unApprovedBook in $unApprovedBookList)
<input type="text" id="bookNum" value="$unApprovedBook.getId().getBookNumid()">
#set($i = $i + 1)
By doing so i am seeing $unApprovedBook.getId().getBookNumid() in UI
if I change the code to:
#foreach($unApprovedBook in $unApprovedBookList)
<input type="text" id="bookNum" value="$unApprovedBook">
#set($i = $i + 1)
I am seeing: [Ljava.lang.Object;#3160316 in UI.
Please let me know what how can I iterate my javaobject in Velocity.
[1]: https://i.stack.imgur.com/eBrYQ.jpg
Try this Way:
You should use property expression $unApprovedBook.id.BookNum. Try To follow Java naming convention.
<input type="text" id="bookNum" value="${unApprovedBook.id.BookNum}">

confirm-ack and confirm-nack channel not getting invoked

I am trying to configure the ack & nack channel and am getting the error like
"Only one confirm call back channel can be configured at a time"
Below are the things which I tried:
1. confirm-correlation-expression="#root" //no result found
2. Changed the amqp template like below
<rabbit:connection-factory id="connectionFactory" host="localhost" publisher-confirms="true" publisher-returns="true" />
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" mandatory="true" /> <!-- for nacks -->
<rabbit:admin connection-factory="connectionFactory" />
/>
The error was not there but the ack channel is not getting invoked.
Can anyone help me on this?
Here the MQ config
<rabbit:template id="nonTransactionalRabbitTemplate"
connection-factory="nonTransactionalConnectionFactory"
mandatory="true"
channel-transacted="false"
confirm-callback="confirmCallback"
return-call`enter code here`back="returnCallback" />
<rabbit:connection-factory id="nonTransactionalConnectionFactory"
connection-factory="rabbitClientConnectionFactory"
publisher-confirms="true"
publisher-returns="true"/>
<rabbit:connection-factory id="nonTransactionalConnectionFactory"
connection-factory="rabbitClientConnectionFactory"
publisher-confirms="true"
publisher-returns="true"/>
<bean id="rabbitClientConnectionFactory" class="com.rabbitmq.client.ConnectionFactory" >
<property name="uri" value="${mq.uri}" />
<property name="requestedHeartbeat" value="30" />
</bean>
Here is my outbound adapter
<int-amqp:outbound-channel-adapter channel="abc"
routing-key="xyz"
amqp-template="amqpTemplate"
confirm-correlation-expression="payload"
confirm-ack-channel="successRespTransformChannel"
confirm-nack-channel="failureRespTransformChannel"
return-channel="failureRespTransformChannel"
mapped-request-headers="*"
Here is my service activator
<chain input-channel="successRespTransformChannel">
<int:header-enricher>
<error-channel ref="failed-publishing" />
</int:header-enricher>
<service-activator id="successResp" expression="#abc.addRequestTracking(payload.id,'success')"/>
</chain>
When using the template in the adapter, you must NOT set your own callbacks
confirm-callback="confirmCallback"
return-callback="returnCallback" />
The adapter sets itself as the callback for both confirms and returns. This fails since you have already set the callbacks.
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" mandatory="true" /> <!-- for nacks -->
mandatory enables returns, not nacks.
EDIT
I have no idea what you are doing wrong. I just wrote a quick test case...
#SpringBootApplication
#ImportResource("context.xml")
public class So36546646Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = SpringApplication.run(So36546646Application.class, args);
ctx.getBean("out", MessageChannel.class).send(new GenericMessage<>("foo"));
boolean received = ctx.getBean(MyService.class).latch.await(10, TimeUnit.SECONDS);
if (!received) {
System.err.println("Did not receive ack");
}
ctx.getBean(RabbitAdmin.class).deleteQueue(ctx.getBean(Queue.class).getName());
ctx.close();
}
public static class MyService {
private final CountDownLatch latch = new CountDownLatch(1);
public void handle(Message<?> ack) {
System.out.println("ack:" + ack);
latch.countDown();
}
}
}
and
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<rabbit:connection-factory id="cf" publisher-confirms="true" publisher-returns="true" host="localhost" />
<rabbit:template id="t" connection-factory="cf" mandatory="true" />
<rabbit:admin connection-factory="cf" />
<rabbit:queue id="anon" />
<int:channel id="out" />
<int-amqp:outbound-channel-adapter
channel="out"
amqp-template="t"
routing-key="#{anon.name}"
confirm-correlation-expression="payload"
confirm-ack-channel="acks"
confirm-nack-channel="acks"
return-channel="returns" />
<int:service-activator input-channel="acks" ref="service" />
<bean id="service" class="com.example.So36546646Application$MyService" />
<int:channel id="returns">
<int:queue />
</int:channel>
</beans>
and it worked fine:
ack:GenericMessage [payload=foo, headers={amqp_publishConfirm=true, id=5eed89bf-11b6-76a5-34ed-0091c6bac2c8, timestamp=1460464254229}]

Entity Framework - Id of loaded entity not being assigned

I have the following POCO class:
public class Person : Entity
{
public string FirstName { get; set; }
public string MiddleName1 { get; set; }
public string MiddleName2 { get; set; }
public string LastName { get; set; }
public byte? DayOfBirth { get; set; }
public byte? MonthOfBirth { get; set; }
public Int16? YearOfBirth { get; set; }
public string MobileNumber { get; set; }
}
public abstract class Entity
{
public int Id { get; set; }
}
Here is the corresponding edmx xml:
<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 Namespace="EntityFramework.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="EntityFrameworkStoreContainer">
<EntitySet Name="People" EntityType="EntityFramework.Store.People" store:Type="Tables" Schema="dbo" />
</EntityContainer>
<EntityType Name="People">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" Nullable="false" />
<Property Name="FirstName" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="MiddleName1" Type="nvarchar" MaxLength="50" />
<Property Name="MiddleName2" Type="nvarchar" MaxLength="50" />
<Property Name="LastName" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="DayOfBirth" Type="tinyint" />
<Property Name="MonthOfBirth" Type="tinyint" />
<Property Name="YearOfBirth" Type="smallint" />
<Property Name="MobileNumber" Type="varchar" MaxLength="20" />
</EntityType>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="EntityFramework" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityContainer Name="TheCleavesEntities" annotation:LazyLoadingEnabled="true">
<EntitySet Name="People" EntityType="EntityFramework.Person" />
</EntityContainer>
<EntityType Name="Person">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Int32" Nullable="false" />
<Property Name="FirstName" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="MiddleName1" Type="String" MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="MiddleName2" Type="String" MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="LastName" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="DayOfBirth" Type="Byte" Nullable="true" />
<Property Name="MonthOfBirth" Type="Byte" Nullable="true" />
<Property Name="YearOfBirth" Type="Int16" Nullable="true" />
<Property Name="MobileNumber" Type="String" MaxLength="20" Unicode="false" FixedLength="false" />
</EntityType>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
<EntityContainerMapping StorageEntityContainer="EntityFrameworkStoreContainer" CdmEntityContainer="TheCleavesEntities">
<EntitySetMapping Name="People"><EntityTypeMapping TypeName="EntityFramework.Person"><MappingFragment StoreEntitySet="People">
<ScalarProperty Name="Id" ColumnName="Id" />
<ScalarProperty Name="FirstName" ColumnName="FirstName" />
<ScalarProperty Name="MiddleName1" ColumnName="MiddleName1" />
<ScalarProperty Name="MiddleName2" ColumnName="MiddleName2" />
<ScalarProperty Name="LastName" ColumnName="LastName" />
<ScalarProperty Name="DayOfBirth" ColumnName="DayOfBirth" />
<ScalarProperty Name="MonthOfBirth" ColumnName="MonthOfBirth" />
<ScalarProperty Name="YearOfBirth" ColumnName="YearOfBirth" />
<ScalarProperty Name="MobileNumber" ColumnName="MobileNumber" />
</MappingFragment></EntityTypeMapping></EntitySetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<Designer xmlns="http://schemas.microsoft.com/ado/2008/10/edmx">
<Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</Connection>
<Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true" />
<DesignerProperty Name="EnablePluralization" Value="True" />
<DesignerProperty Name="IncludeForeignKeysInModel" Value="False" />
</DesignerInfoPropertySet>
</Options>
<!-- Diagram content (shape and connector positions) -->
<Diagrams>
<Diagram Name="TheCleaves">
<EntityTypeShape EntityType="EntityFramework.Person" Width="1.5" PointX="0.75" PointY="0.75" Height="2.7494921874999996" IsExpanded="true" />
</Diagram>
</Diagrams>
</Designer>
</edmx:Edmx>
When I load up an entity (there's only one row in the database at present) with the code:
IEnumerable<Person> people = context.People.Where(x => true);
I'm finding that the Id property of the returned Person object is 0 (it's 1 in the database). Anyone have any idea why it appears not to be set?
Thanks
Ok it is not problem with inheritance as I initially thought - the inheritance will work. This is most probably combination of two problems:
Id is generated in the database but EF doesn't know about them. Both SSDL and CSDL part of EDMX should define Id with StoreGeneratedPattern.Identity. This will force EF to reload Id when entity is inserted.
I believe you are using same context instance for saving entity and calling the query. Now you meet identity map pattern. Despite the data retrieved from the query EF will use instance internally stored in its per-context cache. Because of the first problem the cached instance has Id with default int value = 0.

does Entity framework support user defined functions as scalar properties

I would like to include the value of a scalar function as a read-only property of an entity, since that I could include that value in a filter, is such a thing possible?
The solution is to add a DefiningQuery like in the following sample:
<!-- SSDL content -->
<EntitySet Name="Emp" EntityType="TestModel.Store.Emp" >
<DefiningQuery>
SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, dbo.MyFunc(DEPTNO) AS DNAME FROM EMP
</DefiningQuery>
</EntitySet>
<EntityType Name="Emp">
<Key>
<PropertyRef Name="EMPNO" />
</Key>
<Property Name="EMPNO" Type="int" Nullable="false" />
...
<Property Name="DNAME" Type="varchar" MaxLength ="20" />
</EntityType>
...
<!-- CSDL content -->
...
<EntityType Name="Emp">
<Key>
<PropertyRef Name="EMPNO" />
</Key>
<Property Name="EMPNO" Type="Int32" Nullable="false" />
...
<Property Name="DNAME" Type="String" MaxLength="20" Unicode="false" FixedLength="false" />
</EntityType>
<!-- C-S mapping content -->
...
<ScalarProperty Name="EMPNO" ColumnName="EMPNO" />
...
<ScalarProperty Name="DNAME" ColumnName="DNAME" />
...
The usage example:
using(TestEntities4 db = new TestEntities4()) {
var q = from e in db.Emp where e.DNAME == "RESEARCH" select e;
}
In EF4 you can define a partial class of the same name as your Entity Framework class in the same namespace and add read-only properties to that. I've just done that to expose the description of a connected Entity object as a read-only property of the original object.
namespace same.as.the.data.model
{
public partial class Order
{
public string CustomerName
{
get { return Customer.Name; }
}
}
}

Resources