Error Message:
The data reader returned by the store data provider does not have enough columns for the query requested.
public ObjectResult<global::System.String> P_GET_MST_CODE(global::System.String i_RES_TYPE, ObjectParameter v_RESULT)
{
ObjectParameter i_RES_TYPEParameter;
if (i_RES_TYPE != null)
{
i_RES_TYPEParameter = new ObjectParameter("I_RES_TYPE", i_RES_TYPE);
}
else
{
i_RES_TYPEParameter = new ObjectParameter("I_RES_TYPE", typeof(global::System.String));
}
return base.ExecuteFunction<global::System.String>("P_GET_MST_CODE", i_RES_TYPEParameter, v_RESULT);
}
Below is the definition of the stored procedure.
<Function Name="P_GET_MST_CODE" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="LEGACY">
<Parameter Name="I_RES_TYPE" Type="varchar2" Mode="In" />
<Parameter Name="V_RESULT" Type="varchar2" Mode="Out" />
</Function>
Can anyone help me to solve this problem?
I've solved this by avoiding entity connection object. :-)
Until now, It seems to be unsupported for OUT Parameter of ORACLE Database.
Below is the changed code example.
using System.Data;
using System.Data.Common;
using System.Data.EntityClient;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Server;
using Oracle.DataAccess.Client;
.......
[Invoke]
public string method(string OTL)
{
DbCommand cmd = (((EntityConnection)this.ObjectContext.Connection).StoreConnection).CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "LoveMe";
OracleParameter ep = new OracleParameter("I_RES_TYPE", OTL);
ep.OracleDbType = OracleDbType.Varchar2;
ep.Direction = ParameterDirection.Input;
OracleParameter epV_RESULT = new OracleParameter("V_RESULT", null);
epV_RESULT.OracleDbType = OracleDbType.Varchar2;
epV_RESULT.Size = 30;
epV_RESULT.Direction = ParameterDirection.Output;
cmd.Parameters.Add(ep);
cmd.Parameters.Add(epV_RESULT);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
string result = cmd.Parameters[1].Value.ToString(); //What I want to get.
cmd.Connection.Close();
return result;
}
Related
As you can see the Availability Flag, BeamId is getting repeated. How do I traverse and set the property for Availability Flag1 and so on, so that I can later fetch it with velocity template?
Payload:<ns2:TransportFeasibilityResponse>
<ns2:Parameters>
<ns2:AvailabilityFlag>true</ns2:AvailabilityFlag>
<ns2:SatellitedID>H1B</ns2:SatellitedID>
<ns2:BeamID>675</ns2:BeamID>
<ns2:TransportName>Earth</ns2:TransportName>
</ns2:FeasibilityParameters>
<ns2:Parameters>
<ns2:AvailabilityFlag>true</ns2:AvailabilityFlag>
<ns2:SatellitedID>J34</ns2:SatellitedID>
<ns2:BeamID>111</ns2:BeamID>
<ns2:TransportName>Jupiter</ns2:TransportName>
</ns2:Parameters>
</ns2:TransportFeasibilityResponse>
</ns2:TransportFeasibilityResponseMsg>
Code: (Its not complete)
public static HashMap<String,String> extractNameValueToProperties(String msgBody, selectedKeyList, namelist) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setExpandEntityReferences(false);
factory.setNamespaceAware(true);
Document doc = null;
try{
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(new InputSource(new StringReader(msgBody)));
} catch(Exception ex) {
Exception actException = new Exception( "Exception while extracting tagvalues", ex);
throw actException;
}
HashMap<String,String> tagNameValueMap = new HashMap<String,String>();
NodeList nodeList = doc.getElementsByTagName("*");
// Trying to enter the TransportFeasibilityResponse element
for (int i = 0; i < nodeList.getLength(); i++) {
Node indNode = nodeList.item(i);
if (indNode.indexOf(String name)>-1);
//checking for Availability flag and similar namelist
dataKey = indNode.getTextContent();
message.setProperty(selectedKeyList[k], dataKey);
k++;
j++;
else
{
continue;
}
}
}
Here,
I am setting these values in my route:
<setProperty propertyName="namelist">
<constant>AvailabilityFlag,SatellitedID,BeamID</constant>
</setProperty>
<setProperty propertyName="selectedKeyList">
<constant>AvailabilityFlag1,SatellitedID1,BeamID1,AvailabilityFlag2,SatellitedID2,BeamID2 </constant>
</setProperty>
<bean beanType="com.gdg.dgdgdg.javacodename" method="extractNameValueToProperties"/>
Question: Please tell me how I can parse through the repeating elements and assign it to the property?
Thanks
I'm not sure if I understand your question correctly, but I think you could use the Splitter pattern to split your xml per Parameters tag and process each other separately and aggregate it later.
Take for example this input:
<TransportFeasibilityResponse>
<Parameters>
<AvailabilityFlag>true</AvailabilityFlag>
<SatellitedID>H1B</SatellitedID>
<BeamID>675</BeamID>
<TransportName>Earth</TransportName>
</Parameters>
<Parameters>
<AvailabilityFlag>true</AvailabilityFlag>
<SatellitedID>J34</SatellitedID>
<BeamID>111</BeamID>
<TransportName>Jupiter</TransportName>
</Parameters>
</TransportFeasibilityResponse>
A route to process this input could be something like this:
from("direct:start")
.split(xpath("/TransportFeasibilityResponse/Parameters"), new AggregationStrategy() {
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
List<String> beamIDs = null;
if (oldExchange == null) { // first
beamIDs = new ArrayList<String>();
} else {
beamIDs = oldExchange.getIn().getBody(List.class);
}
beamIDs.add(newExchange.getIn().getBody(String.class));
newExchange.getIn().setBody(beamIDs);
return newExchange;
}
})
.setBody(xpath("/Parameters/BeamID/text()"))
.end()
.log("The final body: ${body}");
First, we split the input per Parameters tag, and then extract the BeamID from it. After that, the AggregationStrategy aggregates each message into one, grouping by BeamID.
The final message should have the a body like this:
675,111
The data I put in the body just for an example, but you could set anywhere you want into the Exchange you are manipulating inside the AggregationStrategy implementation.
I have the following response from a SOAP message. I need to read the values from the REQUEST_STATUS tag and the RESULT tag and put it in a datatable to update the table inside my database.
Please help me as I am doing this for the first time.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<CalculationResponse xmlns="http://www.someurl.com/">
<OUTPUT>
<REQUEST_STATUS>
<IS_SUCCESS>true</IS_SUCCESS>
<IS_PARTIAL_SUCCESS>true</IS_PARTIAL_SUCCESS>
</REQUEST_STATUS>
<RESULT>
<Value>
<inset1>1<inset1>
</Value>
<Value>
<inset2>2<inset2>
</Value>
</RESULT>....
C# Code I tried:
XDocument doc = XDocument.Load(Environment.CurrentDirectory + "\\out.xml");
XNamespace ns = #"http://www.someurl.com/";
bool validation = false;
var root = doc.Descendants("CalculationResponse").Elements("OUTPUT").Elements("REQUEST_STATUS");
var valuestr = from r in root.Elements("IS_SUCCESS")
select r.Value;
validation = (valuestr.ToString()=="true")?true:false;
I always get the valuestr has no results in the collection.
Here is the code I made it to achieve:
C# Code:
XNamespace ns = #"http://www.someurl.com";
bool validation = false;
var parent = doc.Root.Descendants(ns + "CalculationResponse").Descendants(ns + "OUTPUT");
var valuestr = (from r in parent.Descendants(ns + "REQUEST_STATUS").Descendants(ns + "IS_SUCCESS")
select r.Value).ToList();
validation = (valuestr[0] == "true") ? true : false;
I have to display DLFileEntry records based on the expando value. I have followed the link https://www.liferay.com/community/wiki/-/wiki/Main/Search+for+objects+by+custom+attributes which I felt was clear enough.
When I implemented the same thing here...I get the 'no records availble'..
The primary key values I am getting from the loop are present in DLFileEntryMetadata but not in DLFileEntry table. So, the default message is getting displayed that no records are available.
<liferay-ui:search-container delta="5" emptyResultsMessage=
"no-records-available- for-employee" deltaConfigurable="true" >
<liferay-ui:search-container-results>
<%
long classNameId = ClassNameLocalServiceUtil.getClassNameId(DLFileEntry.class);
long companyId = PortalUtil.getDefaultCompanyId();
List<ExpandoValue> values = ExpandoValueLocalServiceUtil.getColumnValues(companyId,
classNameId, ExpandoTableConstants.DEFAULT_TABLE_NAME,
"employeeId",String.valueOf(employeeId), -1, -1);
out.println(values.isEmpty());
List<DLFileEntry> empFiles = new ArrayList<DLFileEntry>();
DLFileEntry fileEntry;
for (int i = 0; i < values.size(); i++) {
long fileId = values.get(i).getClassPK();
try{
out.println(userId);
fileEntry = DLAppLocalServiceUtil.getFileEntry(fileId);
empFiles.add(fileEntry);
}catch(Exception e ){
}
}
searchContainer.setResults(empFiles);
total = results.size();
pageContext.setAttribute("results", results);
pageContext.setAttribute("total", total);
%>
</liferay-ui:search-container-results>
<liferay-ui:search-container-row className="com.liferay.portlet.documentlibrary.model.DLFileEntry" modelVar="fileEntry" rowVar="curRow"
escapedModel="<%=true %>">
<liferay-ui:search-container-column-text orderable="true" name="Name"
property="name" />
<liferay-ui:search-container-column-text orderable="true" name="Extension"
property="extension"/>
<liferay-ui:search-container-column-text orderable="true" name="Mime Type"
property="mimeType"/>
<liferay-ui:search-container-column-text orderable="true" name="Title"
property="title"/>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator/>
the id you get in line:
long fileId = values.get(i).getClassPK();
is not file id but file version id. Try to replace your line:
fileEntry = DLAppLocalServiceUtil.getFileEntry(fileId);
with following one:
fileEntry = DLAppLocalServiceUtil.getFileVersion(fileId).getFileEntry();
br, Pawel
Since FileEntry cannot be cast to DLFileEntry, it is better to get the fileEntryId from this line
long fileEntryId2 = DLAppLocalServiceUtil.getFileVersion(fileId).getFileEntryId();
Then
fileEntry = DLFileEntryLocalServiceUtil.getDLFileEntry(fileEntryId2);
I use simple Console application with database and generated .edmx file. When I insert new row and track update I see that all is ok. But when I go to view the content of my database I dont see any changes.All looks like I was updated "memory instance" of my database.What should I change in my ConnectionString OR/AND .edmx file for updating real database?
UPDATE
<connectionStrings>
<add name="ProductsEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="data source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\Products.mdf;integrated security=True;user instance=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
static void Main(string[] args)
{
var context = new ProductsEntities(ConfigurationManager.ConnectionStrings["ProductsEntities"].ConnectionString);
var productForInsert = new Product {CompanyName = "Insert Name", Price = new decimal(22), Description = "dd", Name = "ddd"};
context.Products.AddObject(productForInsert);
context.SaveChanges();
// return only new row as expected ([database rows].CompanyName == "Toshiba")
// tracking database rows returns expected result too
var result = context.Products.Where(p => p.CompanyName != "Toshiba");
foreach (var b in result)
{
Console.WriteLine(b.CompanyName);
}
}
I am working with a system that has many stored procedures that need to be displayed. Creating entities for each of my objects is not practical.
Is it possible and how would I return a DataTable using ExecuteStoreQuery ?
public ObjectResult<DataTable> MethodName(string fileSetName) {
using (var dataContext = new DataContext(_connectionString))
{
var returnDataTable = ((IObjectContextAdapter)dataContext).ObjectContext.ExecuteStoreQuery<DataTable>("SP_NAME","SP_PARAM");
return returnDataTable;
}
Yes it's possible, but it should be used for just dynamic result-set or raw SQL.
public DataTable ExecuteStoreQuery(string commandText, params Object[] parameters)
{
DataTable retVal = new DataTable();
retVal = context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();
return retVal;
}
Edit: It's better to use classical ADO.NET to get the data model rather than using Entity Framework because most probably you cannot use DataTable even if you can run the method: context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();
ADO.NET Example:
public DataSet GetResultReport(int questionId)
{
DataSet retVal = new DataSet();
EntityConnection entityConn = (EntityConnection)context.Connection;
SqlConnection sqlConn = (SqlConnection)entityConn.StoreConnection;
SqlCommand cmdReport = new SqlCommand([YourSpName], sqlConn);
SqlDataAdapter daReport = new SqlDataAdapter(cmdReport);
using (cmdReport)
{
SqlParameter questionIdPrm = new SqlParameter("QuestionId", questionId);
cmdReport.CommandType = CommandType.StoredProcedure;
cmdReport.Parameters.Add(questionIdPrm);
daReport.Fill(retVal);
}
return retVal;
}
No, I don't think that'll work - Entity Framework is geared towards returning entities and isn't meant to return DataTable objects.
If you need DataTable objects, use straight ADO.NET instead.
This method uses the connection string from the entity framework to establish an ADO.NET connection, to a MySQL database in this example.
using MySql.Data.MySqlClient;
public DataSet GetReportSummary( int RecordID )
{
var context = new catalogEntities();
DataSet ds = new DataSet();
using ( MySqlConnection connection = new MySqlConnection( context.Database.Connection.ConnectionString ) )
{
using ( MySqlCommand cmd = new MySqlCommand( "ReportSummary", connection ) )
{
MySqlDataAdapter adapter = new MySqlDataAdapter( cmd );
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.SelectCommand.Parameters.Add( new MySqlParameter( "#ID", RecordID ) );
adapter.Fill( ds );
}
}
return ds;
}
Yes it can easily be done like this:
var table = new DataTable();
using (var ctx = new SomeContext())
{
var cmd = ctx.Database.Connection.CreateCommand();
cmd.CommandText = "Select Col1, Col2 from SomeTable";
cmd.Connection.Open();
table.Load(cmd.ExecuteReader());
}
By the rule, you shouldn't use a DataSet inside a EF application. But, if you really need to (for instance, to feed a report), that solution should work (it's EF 6 code):
DataSet GetDataSet(string sql, CommandType commandType, Dictionary<string, Object> parameters)
{
// creates resulting dataset
var result = new DataSet();
// creates a data access context (DbContext descendant)
using (var context = new MyDbContext())
{
// creates a Command
var cmd = context.Database.Connection.CreateCommand();
cmd.CommandType = commandType;
cmd.CommandText = sql;
// adds all parameters
foreach (var pr in parameters)
{
var p = cmd.CreateParameter();
p.ParameterName = pr.Key;
p.Value = pr.Value;
cmd.Parameters.Add(p);
}
try
{
// executes
context.Database.Connection.Open();
var reader = cmd.ExecuteReader();
// loop through all resultsets (considering that it's possible to have more than one)
do
{
// loads the DataTable (schema will be fetch automatically)
var tb = new DataTable();
tb.Load(reader);
result.Tables.Add(tb);
} while (!reader.IsClosed);
}
finally
{
// closes the connection
context.Database.Connection.Close();
}
}
// returns the DataSet
return result;
}
In my Entity Framework based solution I need to replace one of my Linq queries with sql - for efficiency reasons.
Also I want my results in a DataTable from one stored procedure so that I could create a table value parameter to pass into a second stored procedure. So:
I'm using sql
I don't want a DataSet
Iterating an IEnumerable probably isn't going to cut it - for efficiency reasons
Also, I am using EF6, so I would prefer DbContext.SqlQuery over ObjectContext.ExecuteStoreQuery as the original poster requested.
However, I found that this just didn't work:
_Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();
This is my solution. It returns a DataTable that is fetched using an ADO.NET SqlDataReader - which I believe is faster than a SqlDataAdapter on read-only data. It doesn't strictly answer the question because it uses ADO.Net, but it shows how to do that after getting a hold of the connection from the DbContext
protected DataTable GetDataTable(string sql, params object[] parameters)
{
//didn't work - table had no columns or rows
//return Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();
DataTable result = new DataTable();
SqlConnection conn = Context.Database.Connection as SqlConnection;
if(conn == null)
{
throw new InvalidCastException("SqlConnection is invalid for this database");
}
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddRange(parameters);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
result.Load(reader);
}
return result;
}
}
The easiest way to return a DataTable using the EntityFramework is to do the following:
MetaTable metaTable = Global.DefaultModel.GetTable("Your EntitySetName");
For example:
MetaTable metaTable = Global.DefaultModel.GetTable("Employees");
Maybe your stored procedure could return a complex type?
http://blogs.msdn.com/b/somasegar/archive/2010/01/11/entity-framework-in-net-4.aspx