Petapoco - Calling Oracle pipelined function results in "Unsupported column datatype" exception - petapoco

I calling a pipelined function in Oracle, I'm getting an "Unsupported column datatype" error and not sure how to remedy this.
Here's the code, this is a little simpler than it is in reality but it works exactly the same:
CREATE OR REPLACE FUNCTION CIC3.F_SUG_PUBS_BY_DESIGS(p_desigs in VARCHAR2)
RETURN SUG_PUBS_TBL PIPELINED IS
BEGIN
FOR r IN (
SELECT invid, title, desc, price, fin, desig FROM v_sugpubs WHERE desig = p_desigs
)
LOOP
PIPE ROW(SUG_PUBS_T(r.invid, r.title, r.desc, r.price, r.fin, r.desig));
END LOOP;
RETURN;
END F_SUG_PUBS_BY_DESIGS;
/
Here's the 2 types:
CREATE OR REPLACE TYPE SUG_PUBS_TBL AS TABLE OF SUG_PUBS_T
/
CREATE OR REPLACE TYPE CIC3.SUGGESTED_PUBS_T AS OBJECT
(
invid VARCHAR2(15),
title VARCHAR2(300),
desc VARCHAR2(500),
price VARCHAR2(5),
fin NUMBER(15),
desig VARCHAR2(5)
)
/
Here's my service call:
public object Get(SugPubsRequest request)
{
if (QryPidFromLT(request.LT) == request.PID)
{
List<SugPubsResponse> p = GetSugPubs(request.Desigs);
return p;
}
else
{
throw new AuthenticationException("Invalid LT");
}
}
private List<SugPubsResponse> GetSugPubs(string Desigs)
{
var db = new PetaPoco.Database("Settings.Oracle");
var sql = "SELECT F_SUG_PUBS_BY_DESIGS('" + Desigs + "') FROM DUAL";
List<SugPubsResponse> _sc = db.Fetch<SugPubsResponse>(sql);
return _sc;
}
And here's the Models:
[Route("/SugPubs/{LT}/{PID}/{Desigs}")]
public class SugPubsRequest
{
public string LT { get; set; }
public int PID { get; set; }
public string Desigs { get; set; }
}
public class SugPubsResponse
{
[PetaPoco.Column("invid")]
public string InvId { get; set; }
[PetaPoco.Column("title")]
public string Title { get; set; }
[PetaPoco.Column("desc")]
public string Desc { get; set; }
[PetaPoco.Column("price")]
public string Price { get; set; }
[PetaPoco.Column("fin")]
public int Fin { get; set; }
[PetaPoco.Column("desig")]
public string Desig { get; set; }
}

To allow others to make it work, I did this to get the results:
All you have to do is change the SQL in your service call:
var sql = "SELECT * FROM TABLE(F_SUG_PUBS_BY_DESIGS('" + Desigs + "'))";

Related

How to rewrite Entity Framework query to SQL Server query

I have a table called passenger policy that looks like this:
public Guid HotelId { get; set; }
public int FromAge { get; set; }
public int ToAge { get; set; }
public PassengerType PassengerType { get; set; }
and it has 3 rows for each HotelId key.
I have another table called search that looks like this
public class Search : BaseEntity
{
public DateTime Date { get; set; }
public Guid CountryId { get; set; }
public Guid ProvinceId { get; set; }
public Guid CityId { get; set; }
public Guid HotelId { get; set; }
public Guid VendorHotelRoomId { get; set; }
public int StandardCapacity { get; set; }
public int ExtraCapacity { get; set; }
public int MaxInfantAge { get; set; }
public int MaxChild1Age { get; set; }
public int MaxChild2Age { get; set; }
public double BasePrice { get; set; }
public double ExtraAdultPrice { get; set; }
public double ExtraInfantPrice { get; set; }
public double ExtraChild1Price { get; set; }
public double ExtraChild2Price { get; set; }
}
I want to write a query in T-SQL (SQL Server) to get hotels based on date field, standard capacity and extra capacity.
The extra capacity has 3 possible values:
infant
child 1
child 2
(fetched from passenger type table)
I write it like this in EF Core
var searchOnAllVendors hotelContext.Search
.Where(c => c.Date >= fromDate
&& c.Date <= toDate
&& c.CityId == cityId
&& c.ExtraCapacity >= adultCount)
.AsEnumerable();
foreach (var item in searchOnAllVendors)
{
foreach (var ag in request.Passengers.ChildrensAges)
{
if (ag <= item.MaxInfantAge && ag < item.MaxChild1Age && ag < item.MaxChild2Age)
infant++;
if (ag > item.MaxInfantAge && ag <= item.MaxChild1Age)
child1Count++;
if (ag > item.MaxChild1Age && ag <= item.MaxChild2Age)
child2Count++;
if (ag > item.MaxChild1Age && ag <= item.MaxChild2Age)
extraAdult++;
}
if (item.MaxInfantAge >= infant && item.MaxChild1Age >= child1Count && item.MaxChild2Age >= child2Count)
{
var adulPrice = extraAdult * item.ExtraAdultPrice;
var infantPrice = infant * item.ExtraInfantPrice;
var child1Price = child1Count * item.ExtraChild1Price;
var child2Price = child1Count * item.ExtraChild2Price;
var finalPrice = adulPrice + infantPrice + child1Price + child2Price + item.BasePrice;
searches.Add(new Search_Response
{
CityId = item.CityId,
CountryId = item.CountryId,
HotelId = item.HotelId,
ProvinceId = item.ProvinceId,
VendorHotelRoomId = item.VendorHotelRoomId,
Price = finalPrice
});
}
}
after couple days and try a few things i find a way to have best performance in T-SQL
...
1. Get count of extra passernger types in scalar-valued functions like this :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetChildRule](#ages as nvarchar(max),#min as int,#max as int)
RETURNS int
AS
BEGIN
declare #count int
select #count=count(*) from STRING_SPLIT(#ages,',')
where value > #min and value <= #max
RETURN #count
END
...
and use it in stored procedure like a field as below :
select * , GetChildRule('1,2,3',mymin,mymax) from Search where date between date1 and date2
and call it in EF CORE:
Context.Set<YourModelWithAllOfFiledYouReturnInSP>()
.FromSqlRaw($"EXEC [dbo].[StaySearch] #extraAges = N'{ages}',
#checkInDate = N'{fromDate}', #checkOutDate = N'{toDate}',
#destinationId = '{destinationId}',
#countrySearch = '{countrysearch}',#adultCount={adultCount}");

How to write unit test for mvc. In class a method return a list?

I need to write unit test for below code. Easy understanding of the solution. I novice for unit testing. I don't know how write. I have added unit test class successfully from solution explorer.
class 1:
public class ListModel
{
public int EmpID { get; set; }
public string EmpName {get;set;}
public string CusID {get; set;}
public string EmpType { get; set; }
public string EmpPDLC { get; set; }
public int? EmpMode { get; set; }
public int? Status { get; set; }
}
class 2:
public class EmployeeHelper : IEmployeeHelper
{
public List<ListModel> EmployeeList(int userId)
{
var lstModel = new List<ListModel>();
try
{
using (var dc = new EmployeeDataContext())
{
var lstGetTable = (from table in dc.UserTables
where table.UserID == userId && table.Status == 1
select table).ToList();
lstModel.AddRange(lstGetTable.Select(items => new ListModel
{
EmpID = items.EmpID,
EmpName = items.EmpName,
CustID = items.CustID,
EmpType = items.EmpType,
EmpPDLC = items.EmpPDLC,
EmpMode = items.EmpMode,
Status = items.Status
}));
}
}
catch (Exception)
{
return lstModel;
}
return lstModel;
}
}

Returning a String from a SQL query in MVC Entity Framework 6 Controller

I want to execute a basic SQL query (e.g. "SELECT string FROM table WHERE criteria = TRUE) on MVC Entity Framework 6. The returned type is to be a string. I have tried many possible things but they return the SQL query string or something completely irrelevant, such as:
SELECT [Extent1].[Fname] AS [Fname]
FROM [dbo].[Developer] AS [Extent1]
WHERE ([Extent1].[Login] = #p__linq__0)
OR (([Extent1].[Login] IS NULL) AND (#p__linq__0 IS NULL))
I have the following in my controller:
var data = db.Developers.Where(y => y.Login.Equals(username)).ToList();
This is my Developers class:
public partial class Developer
{
public int PersonID { get; set; }
public string Fname
{
get { return Fname.ToString(); }
set { Fname = value;}
}
public string Lname { get; set; }
public string Developer1 { get; set; }
public string Login { get; set; }
public Nullable<bool> IsManager { get; set; }
public Nullable<bool> IsPF { get; set; }
public Nullable<bool> IsLW { get; set; }
public string Prov { get; set; }
}
I would like to get the string that this query returns.
Somehow this works when this is made to a List and passed to the View model, where it is displayed using #Html.DisplayFor().
Is there a way to execute my SQL command in my controller and get a string value in return?
FirstOrDefault() to return the first element, in this case there is only one.
You should include a validation if username doesnt exist.
Developer myDeveloper = db.Developers
.Where(y => y.Login.Equals(username))
.ToList()
.FirstOrDefault();
return myDeveloper.Lname;

Ravendb TransformResults showing null values for properties populated with Load()

I have two documents Ticket and MenuItem i have created index with TransformResults but problem is i am getting null value for Loaded document in transform
public class Ticket
{
public int ID { get; set; }
public int ItemId { get; set; }
public string ItemName { get; set; }
public int Price { get; set; }
}
public class MenuItem
{
public int ID { get; set; }
public string ItemName { get; set; }
public string PriceCategory { get; set; }
}
i have created a index like
public class TicketItemGross : AbstractIndexCreationTask<Ticket, TicketItemGross.TicketItemDetails>
{
public class TicketItemDetails
{
public string ID { get; set; }
public string ItemId { get; set; }
public string ItemName { get; set; }
public int Price { get; set; }
public string PriceCategory { get; set; }
}
public TicketItemGross()
{
Map = docs => from doc in docs
select new
{
ID = doc.ID,
ItemId=doc.ItemId,
ItemName=doc.ItemName,
Price=doc.Price
};
TransformResults = (database, docs) => from m in docs
let d = database.Load<MenuItem>(m.ID)
select new
{
ID = m.ID,
ItemId = m.ItemId,
ItemName = m.ItemName,
Price = m.Price,
PriceCategory=d.PriceCategory
};
}
}
and the problem is that when i query data. I get null for PriceCategory but for all other fields i get correct value
here is query
IEnumerable<TicketItemGross.TicketItemDetails> list;
using (var session = store.OpenSession())
{
list = session.Query<TicketItemGross.TicketItemDetails, TicketItemGross>();
}
This is happening because you are using integer IDs. When you call database.Load in your transform, you'll need to manually convert it to a string ID.
database.Load<MenuItem>("MenuItems/" + m.ID)
This is one of several places where Raven gets confused if you use integer or guid IDs. If you use string ids, you won't have this problem.
Also, you might consider using a results transformer instead. They are easier than index transformers, which are now obsolete.

castle activerecord lazy get id

I have these two classes
[ActiveRecord("Customers", Lazy=true)]
public class Customer : ActiveRecordBase<Customer>
{
[PrimaryKey(PrimaryKeyType.Identity, Access = PropertyAccess.AutomaticProperty)]
public virtual int Id { get; private set; }
[Property]
public virtual string Name { get; set; }
[HasMany(Lazy = true)]
public virtual IList<Order> Orders { get; set; }
}
[ActiveRecord("Orders", Lazy=true)]
public class Order : ActiveRecordBase<Order>
{
[PrimaryKey(PrimaryKeyType.Identity, Access = PropertyAccess.AutomaticProperty)]
public virtual int Id { get; private set; }
[Property]
public virtual string Product { get; set; }
[BelongsTo(Lazy = FetchWhen.OnInvoke)]
public virtual Customer Customer { get; set; }
}
I want to select all orders and foreach of them, get the id of the customer.
So I do this:
using (new SessionScope())
{
var orders = Order.FindAll();
foreach (var o in orders)
{
int id = o.Customer.Id;
}
}
It works, but it creates a SELECT phrase for each call to o.Customer.Id.
Now, the Order already has the Id of the customer, so how can I get it without revisiting the database??
the following code should allow you to get the id (but I couldn't test it at the moment):
int id = (int)((INHibernateProxy)order.Customer).HibernateLazyInitializer.Identifier;
Greetings
Juy Juka