Postgres function is not working/calling in hosted web project - postgresql

I have created an ASP.Net Core Web App (MVC) Project which in turns call Web Api for calling the database for getting the values and posting the values. The database used is Postgres. I have written a Postgres function to populate values for a report Day Book. When I run the project through visual studio it works fine. Then I have hosted the project. When I login through hosted ip address and calling the report function returns no values and the reports showing no values.
The Postgres function is given below
CREATE OR REPLACE FUNCTION public.day_book(
d1 date,
d2 date,
cid integer)
RETURNS TABLE(roworder integer, guid uuid, tbl1 text, date1 timestamp without time zone, credit real, debit real, description1 text, credit1 real, debit1 real)
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
BEGIN
RETURN QUERY
SELECT db1."roworder",db1."guid",db1."tbl1",db1."date1",db1."credit",db1."debit",
db1."description1",db1."credit1",db1."debit1"
from "tbldaybook1" as db1 order by db1."date1",db1."roworder";
END;
$BODY$;
The MVC controller method that calls the API controller method is given below
public async Task<JsonResult> GetDayBook(DateTime FromDate, DateTime ToDate)
{
ClaimsPrincipal currentUser = this.User;
var currentUserId = Convert.ToInt32(currentUser.FindFirst("UserId").Value);
var ChurchId = Convert.ToInt32(currentUser.FindFirst("ChurchId").Value);
var Role = currentUser.FindFirst(ClaimTypes.Role).Value;
var isSuperAdmin = Convert.ToBoolean(currentUser.FindFirst("IsSuperAdmin").Value);
var d11 = FromDate.ToString("dd-MM-yyyy");
var d22 = ToDate.ToString("dd-MM-yyyy");
int cid = ChurchId;
List<RptDayBook> daybook = new List<RptDayBook>();
HttpClient client = api.Initial();
HttpResponseMessage responseTask = await client.GetAsync("reports/GetDayBook/" + d11 + "/" + d22 + "/" + cid);
if (responseTask.IsSuccessStatusCode)
{
var readTask = responseTask.Content.ReadAsStringAsync().Result;
daybook = JsonConvert.DeserializeObject<List<RptDayBook>>(readTask);
}
return Json(daybook);
}
The below API method connects to the Postgres database and call the function
[HttpGet("GetDayBook/{d11}/{d22}/{cid}")]
public IEnumerable<RptDayBook> GetDayBook(string d11, string d22, int cid)
{
using (var command = db.Database.GetDbConnection().CreateCommand())
{
DateTime d1 = Convert.ToDateTime(d11);
DateTime d2 = Convert.ToDateTime(d22).AddDays(1);
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "day_book";
command.Parameters.Add(new Npgsql.NpgsqlParameter("d1", NpgsqlTypes.NpgsqlDbType.Date)
{ Value = d1 });
command.Parameters.Add(new Npgsql.NpgsqlParameter("d2", NpgsqlTypes.NpgsqlDbType.Date)
{ Value = d2 });
command.Parameters.Add(new Npgsql.NpgsqlParameter("cid", NpgsqlTypes.NpgsqlDbType.Integer)
{ Value = cid });
if (command.Connection.State == ConnectionState.Closed)
command.Connection.Open();
List<object[]> result = new List<object[]>();
var res = command.ExecuteReader();
if (res.HasRows)
{
while (res.Read())
{
var values = new object[res.FieldCount];
for (int i = 0; i < res.FieldCount; i++)
{
if (i == 4 || i == 5 || i == 7 || i == 8)
{
values[i] = res[i] == DBNull.Value ? 0 : Convert.ToDouble(res[i]);
}
else
{
values[i] = res[i];
}
}
result.Add(values);
}
}
List<RptDayBook> rpt = new List<RptDayBook>();
foreach (var item in result)
{
RptDayBook rptDayBook = new RptDayBook();
rptDayBook.roworder = (int)item[0];
rptDayBook.GUID = (Guid)item[1];
rptDayBook.tbl1 = (string)item[2];
rptDayBook.date1 = (DateTime)item[3];
rptDayBook.credit = item[4] == DBNull.Value ? 0 : Convert.ToDouble(item[4]);
rptDayBook.debit = item[5] == DBNull.Value ? 0 : Convert.ToDouble(item[5]);
rptDayBook.Description1 = (string)item[6];
rptDayBook.credit1 = item[7] == DBNull.Value ? 0 : Convert.ToDouble(item[7]);
rptDayBook.debit1 = item[8] == DBNull.Value ? 0 : Convert.ToDouble(item[8]);
rpt.Add(rptDayBook);
}
return rpt;
}
}
What will be the issue? Is it either the function is not calling or function can't return values?

It is the issue while converting the datetime in the API.
Change the code from
DateTime d1 = Convert.ToDateTime(d11);
to
DateTime d1 = DateTime.ParseExact(d11, "dd-MM-yyyy", CultureInfo.InvariantCulture);
Also do the same in the next line also.

Related

I have to perform calculation on the data coming from database table

services class
Here by using modelVms I am not getting column name, and how do return
variable v1, v2 with modelVms. Because I have to show v1& v2 value
on UI
public async Task<List<ProductivityAndLabourPerHectaresVM>> Get()
{
var models = await _unitOfWork.ProductivityAndLabourPerHectaresRepo.Get().ConfigureAwait(false);
if (models == null || models.Count <= 0)
return null;
var modelVms = _mapper.Map<List<ProductivityAndLabourPerHectaresVM>>(models);
if (modelVms == null || modelVms.Count <= 0) return null;
var v1=modelVMS.NoOfLabour/Area
var v2=modelVMS.Production/Area
return modelVms;
}

C# ExecuteReaderAsync Sporadic Issue

I have a method that is getting a list of users. There is a store procedure that is expected either a username or null. It returns one or more users based on the parameter. It works fine most of the time, but I notice there are times it does not return any result even though I am passing the same exact parameter. I put a break point in the Execute Reader Async, and the line immediately following it. When the issue occurs, it reaches the first break point but not the second one. It does not throw an exception or prevent me from making another call. I can make the next call, and it will return the result as expected. I would appreciate some suggestions as to what may cause this issue?
public async Task<List<User>> GetUsers(string username, int accountType = 1)
{
List<User> users = null;
parameters = new List<SqlParameter>{
new SqlParameter{
DbType = DbType.String,
ParameterName = "#userName",
Value = username.NotEmpty() ? username : (object) DBNull.Value
},
new SqlParameter{
DbType = DbType.Int32,
ParameterName = "#accountType",
Value = accountType
}
};
try
{
using (SqlConnection con = new SqlConnection(conStr))
{
await con.OpenAsync();
using (SqlCommand cmd = new SqlCommand("spGetUsers", con))
{
cmd.Parameters.AddRange(parameters.ToArray());
cmd.CommandType = CommandType.StoredProcedure;
SqlDataReader dr = await cmd.ExecuteReaderAsync()
if (dr.HasRecord())
{
while (await dr.ReadAsync())
{
User user = new User();
user.FirstName = dr["firstName"].ToString();
user.LastName = dr["lastName"].ToString();
user.DateRegister = Convert.ToDateTime(dr["DateRegister"].ToString());
user.Active = Convert.ToBoolean(dr["Active"].ToString());
if(users == null)
{
users = new List<User>();
}
users.Add(user);
}
}
}
}
}
catch (Exception ex)
{
Util.LogError(ex.ToString());
users = null;
}
return users;
}
Update:
Yes, the error is being logged. Also, I added a breakpoint in the catch statement in case an error is thrown.
Here is the query that is used to create that store procedure:
IF EXISTS (SELECT 1 FROM SYS.objects WHERE object_id = OBJECT_ID('spGetUsers') AND TYPE IN (N'PC', N'P'))
DROP PROCEDURE spGetUsers
GO
CREATE PROCEDURE spGetUsers
#userName nvarchar(50),
#accountType int = 1
AS
BEGIN
SELECT U.firstName, U.lastName, U.DateRegister, A.Active
FROM [User] U
inner join UserAccount UA
on U.Id = UA.userid
inner join Account A
on A.Id = UA.accountId
WHERE U.Id > 0
AND UA.Id > 0
AND A.Id > 0
AND UA.AccountType IN (#accountType )
and (A.UserName in (#userName) or #userName IS NULL)
END
Extension Method to check if SQL DataReader has record
public static bool HasRecord(this System.Data.SqlClient.SqlDataReader dr)
{
if (dr != null && dr.HasRows)
{
return true;
}
return false;
}

Salesforce Trigger Test Class

below is my Apex Trigger. I am a beginner and trying to write its test class but continuously getting error "System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Error: You can't select products until you've chosen a price book for this opportunity on the products related list.: []".
trigger TrgrOptyHighestCustmorePrice on Opportunity (before insert, before update)
{
public Id oid;
public String bidType;
public String BUCode;
for(Opportunity o : trigger.new)
{
oid = o.Id;
bidType = o.BidType__c;
BUCode = o.Business_Line_BU__c;
}
List<OpportunityLineItem> oliList = new list<OpportunityLineItem>([SELECT id, Customer_Price__c, ReCat_Product_Line__c
FROM OpportunityLineItem
WHERE OpportunityId =: oid ORDER BY
Customer_Price__c DESC LIMIT 1]);
for(OpportunityLineItem oli : oliList)
{
if(bidType == 'Competitive' && oli.ReCat_Product_Line__c == 'DMS')
{
BUCode = 'BL.619';
}
if(bidType == 'Competitive' && (oli.ReCat_Product_Line__c == 'EMS' || oli.ReCat_Product_Line__c == 'GMS'))
{
BUCode = 'BL.620';
}
if(bidType == 'Competitive' && oli.ReCat_Product_Line__c == 'MMS')
{
BUCode = 'BL.622';
}
if(bidType == 'Sole Sourced' && oli.ReCat_Product_Line__c == 'DMS')
{
BUCode = 'BL.624';
}
if(bidType == 'Sole Sourced' && (oli.ReCat_Product_Line__c == 'EMS' || oli.ReCat_Product_Line__c == 'GMS'))
{
BUCode = 'BL.621';
}
if(bidType == 'Sole Sourced' && oli.ReCat_Product_Line__c == 'MMS')
{
BUCode = 'BL.623';
}
}
for(Opportunity opt : trigger.new)
{
opt.Business_Line_BU__c = BUCode;
}
}
Test Class
#isTest(seeAllData=true)
public class Test_TrgrOptyHighestCustmorePrice {
private static testmethod void TrgrOptyHighestCustmorePriceTest(){
Test.startTest();
//Insert a test product.
Product2 p1 = new Product2(Name='Product Monthly 1111', isActive=true, CurrencyIsoCode='USD', ReCat_Product_Line__c = 'DMS');
insert p1;
// Get standard price book ID.
Id pricebookId = Test.getStandardPricebookId();
// Insert a price book entry for the standard price book.
PricebookEntry standardPrice = new PricebookEntry(
Pricebook2Id = pricebookId, Product2Id = p1.Id,
UnitPrice = 10000, IsActive = true);
insert standardPrice;
Pricebook2 customPB = new Pricebook2(Name='Custom Pricebook', isActive=true);
insert customPB;
PricebookEntry customPrice = new PricebookEntry(
Pricebook2Id = customPB.Id, Product2Id = p1.Id,
UnitPrice = 12000, IsActive = true);
insert customPrice;
// Insert Opportunity
Opportunity opt = new Opportunity(Name='Test',StageName='Prospect',
CloseDate=date.today(),BidType__c = 'Competitive',
Business_Line_BU__c = 'BL.619',
PriceBook2 = customPB);
insert opt;
OpportunityLineItem optLI = new OpportunityLineItem(OpportunityId = opt.id, Product2Id = p1.Id);
insert optLI;
update opt;
Test.stopTest();
}
}
I am unable to understand how can I test my simple trigger.
Its because u do not fill all required fields for the Opportunity Line Item. See: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_opportunitylineitem.htm for required fields.
This as an example will work:
OpportunityLineItem optLI = new OpportunityLineItem(OpportunityId = opt.id, Product2Id = p1.Id, TotalPrice = 100, PricebookEntryId=customPrice.Id, Quantity =3);
First Insert the opportunity.
Then update the opportunity with the pricebookid.
// Insert Opportunity
Opportunity opt = new Opportunity(Name='Test',StageName='Prospect',
CloseDate=date.today(),BidType__c = 'Competitive',
Business_Line_BU__c = 'BL.619'
);
insert opt;
opt.PriceBook2 = customPB;
update opt;

Importing DBF file in SQL Server 2012

I have over 200+ dbf files having different schema. I have used SSIS to import .dbf files, but in order to automate the task I want to use OpenRowset. OpenRowSet is working fine for Excel Files, but not for .dbf.
I have written
SELECT [LRSNum],[AppUpdD],[AppStat],[PIN] FROM OPENROWSET('MICROSOFT.ACE.OLEDB.12.0','dBASE 5.0;Database=D:\Sales- data\SalesSourcefile\2016\December\Shape\Martin\real_land\', 'SELECT [LRSNum],[AppUpdD],[AppStat],[PIN] FROM real_land.dbf');
Any help will be appreciated.
I am using SQL Server 2012, Windows 8.1.
Installed Foxpro driver, but when selected foxpro using DTS, it fails.
FYI - You can do automated uploads of DBFs to SQL Server using SQL Server Upsizing Wizard for FoxPro.
With this tool, you have to do the uploading from FoxPro, and the DBFs must be attached to a FoxPro DBC.
http://www.codemag.com/article/0703052
The latest version if available from the VFPx site.
Finally, this is working
SELECT * FROM OPENROWSET ('MICROSOFT.ACE.OLEDB.12.0','dBase 5.0;HDR=YES;IMEX=2;DATABASE=\Dbf Directory\',
'SELECT * FROM dbf_filename.dbf')
I once had to do this too and wrote some C# code for the import.
Just as a try: With this line I open the connection within C#
var con = new OdbcConnection("Driver={{Microsoft dBASE Driver (*.dbf)}};Dbq=C:\\SomePath;DriverID=277;");
Might be, that you can get something out of this.
Some C# code
The following code is taken from one of my C# projects. I modified it to be neutral, but I cannot guarantee, that this is working right so:
public List<string> Ambus;
public List<string> Tbls;
public List<string> errList;
public List<string> SQLs;
private void btnImport_Click(object sender, EventArgs e) {
SqlConnection sqlcon;
SqlCommand sqlcmd;
SQLs.Clear();
Tbls.Clear();
var con = new OdbcConnection("Driver={{Microsoft dBASE Driver (*.dbf)}};Dbq=C:\\SomePath;DriverID=277;");
con.Open();
var tbls = con.GetSchema(OdbcMetaDataCollectionNames.Tables);
foreach (System.Data.DataRow r in tbls.Rows) {
Tbls.Add(r["TABLE_NAME"].ToString());
}
DataTable cols = null;
var sb = new StringBuilder();
int i = 0;
foreach (var tblnm in Tbls) {
i++;
sb.Clear();
try {
cols = con.GetSchema(OdbcMetaDataCollectionNames.Columns, new string[] { null, null, tblnm, null });
sb.AppendFormat(" CREATE TABLE dbo.[{0}](TableName VARCHAR(100) NOT NULL ", tblnm);
int count = 0;
foreach (DataRow colrow in cols.Rows) {
var colInf = string.Format(" ,{0} {1} NULL", colrow["COLUMN_NAME"].ToString(), this.createDataType(colrow["TYPE_NAME"].ToString(), colrow["COLUMN_SIZE"].ToString(), colrow["DECIMAL_DIGITS"].ToString(), colrow["NUM_PREC_RADIX"].ToString()));
sb.Append(colInf);
count++;
}
sb.Append("); ");
SQLs.Add(sb.ToString());
sb.Clear();
var cmd = new OdbcCommand("SELECT * FROM [" + tblnm + "]", con);
var reader = cmd.ExecuteReader();
while (reader.Read()) {
var vals = createVals(cols, reader, tblnm);
string insStat = string.Format(" INSERT INTO dbo.[{0}] VALUES ('{0}',{1});", tblnm, vals);
SQLs.Add(insStat);
}
}
catch (Exception exo) {
errList.Add(string.Format("{0}:{1}", tblnm, exo.Message));
}
con.Close();
sqlcon = new SqlConnection("Data Source=SomeSQLServer;Initial Catalog=master;User ID=sa;pwd=SomePwd");
sqlcon.Open();
sqlcmd = new SqlCommand("USE SomeTargetDB;", sqlcon);
sqlcmd.ExecuteNonQuery();
i = 0;
foreach (string s in SQLs) {
i++;
//Progress-output: this.Text = string.Format("{0} von {1}", i, SQLs.Count);
sqlcmd = new SqlCommand(s, sqlcon);
sqlcmd.ExecuteNonQuery();
}
sqlcon.Close();
}
}
private string createDataType(string typ, string size, string dec, string prec) {
switch (typ.ToLower()) {
case "char":
return "NVARCHAR(" + size + ")";
case "logical":
return "BIT";
case "numeric":
dec = dec == string.Empty ? null : dec;
prec = prec == string.Empty ? null : prec;
int d = int.Parse(dec ?? "0");
int p = int.Parse(prec ?? "0");
if (d == 0 && p == 0)
return "INT";
else if (d > 0 && p > 0)
return string.Format("DECIMAL({0},{1})", d, p);
else if (d == 0 && p > 0)
return "FLOAT";
else
return null;
case "date":
return "DATETIME";
default:
return null;
}
}
private string createVals(DataTable cols, OdbcDataReader reader, string tblnm) {
var sb = new StringBuilder();
sb.Append("'" + tblnm + "'");
foreach (DataRow colrow in cols.Rows) {
var val = string.Empty;
try {
val = reader[colrow["COLUMN_NAME"].ToString()].ToString();
}
catch { }
if (val.Trim().Length == 0)
val = "NULL";
else {
if (colrow["TYPE_NAME"].ToString().ToLower() == "char")
val = val.Replace("'", "''");
if (colrow["TYPE_NAME"].ToString().ToLower() == "numeric")
val = val.Replace(".", "").Replace(",", ".");
if (colrow["TYPE_NAME"].ToString().ToLower() == "date") {
var d = DateTime.Parse(val, System.Globalization.CultureInfo.CurrentCulture);
if (d.Year < 1900 || d.Year > 2020)
d = new DateTime(1900, d.Month, d.Day, d.Hour, d.Minute, d.Second);
val = d.ToString("dd.MM.yyyy HH:mm:ss");
}
val = "'" + val + "'";
}
sb.AppendFormat(",{0}", val);
}
return sb.ToString();
}

Postgresql update - Using ArrayList

I am getting an exception on update of postgres:
org.postgresql.util.PSQLException: Can't infer the SQL type...
Here is the code where in I build the sql statement dynamically and append the params:
public Boolean update(UserData usrData){
String sqlUpdateUser = "UPDATE \"USER\" ";
String sqlSetValues = "SET";
String sqlCondition = "Where \"USER_ID\" = ? ";
List<Object> params = new ArrayList<Object>();
List<Integer> types = new ArrayList<Integer>();
if(usrData.getFirstName() != null){
sqlSetValues = sqlSetValues.concat(" \"FIRST_NAME\" = ? ").concat(", ");
params.add(usrData.getFirstName());
types.add(Types.VARCHAR);
}
if(usrData.getMiddleName() != null){
sqlSetValues = sqlSetValues.concat("\"MIDDLE_NAME\" = ? ");
params.add(usrData.getMiddleName());
types.add(Types.VARCHAR);
}
params.add(usrData.getUserId());
types.add(Types.BIGINT);
Object[] updateParams = new Object[params.size()];
updateParams = params.toArray(updateParams);
Integer[] paramTypes = new Integer[types.size()];
paramTypes = types.toArray(paramTypes);
sqlUpdateUser = sqlUpdateUser.concat(sqlSetValues).concat(sqlCondition);
int rowsAffected = this.jdbcTemplate.update(sqlUpdateUser, updateParams, paramTypes);
if(rowsAffected > 0){
return Boolean.TRUE;
}else{
return Boolean.FALSE;
}
}
And table schema for the USER table is:
"FIRST_NAME" character varying(50),
"MIDDLE_NAME" character varying(50),
If I do an update statically without using the collection, but by using Array, I see no issue.
Code snipped using arrays:
Object[] param = { usrData.getFirstName(), usrData.getMiddleName(), usrData.getUserId() };
int[] type = { Types.VARCHAR, Types.VARCHAR, Types.BIGINT };
int rowsAffected = this.jdbcTemplate.update(sqlUpdateUser, param, type);
Am I missing something?
Thanks
K
Move these lines
Object[] updateParams = new Object[params.size()];
updateParams = params.toArray(updateParams);
Integer[] paramTypes = new Integer[types.size()];
paramTypes = types.toArray(paramTypes);
beneath
params.add(usrData.getUserId());
types.add(Types.INTEGER);
In your case you are missing to add usrData.getUserId() in updateParams.