Entity framework core, how to use named parameters with oracle procedure - oracle

I have an oracle package with some non mandatory parameters, iam using entity framework to call it but found some difficult in finding correct syntax
looking here i try in that way
string query = "";
var pSoloAttivi = new OracleParameter("ONLY_ATTV", SoloAttivi ? "Y" : "N");
var pIdIncarico = new OracleParameter("ASSIGNMENT_ID", IdIncarico);
query = $"BEGIN PKG_INSP.INSPECTIONS_LIST(#ONLY_ATTV={pSoloAttivi}); END;";
if (!string.IsNullOrWhiteSpace(IdIncarico))
{
query = $"BEGIN PKG_INSP.INSPECTIONS_LIST(#ONLY_ATTV={pSoloAttivi}, #ASSIGNMENT_ID = {pIdIncarico}); END;";
}
return await _context
.Set<DtoElencoIncarichi>()
.FromSqlRaw(query)
.AsNoTracking()
.ToListAsync();
but got error from oracle at '#' character
i try with that
string queryBase = "BEGIN PKG_INSP.INSPECTIONS_LIST({0}); END;";
var query = string.Format(queryBase, "ONLY_ATTV => :ONLY_ATTV");
IEnumerable <OracleParameter> parameters = new List<OracleParameter>();
parameters = parameters.Append(new OracleParameter("ONLY_ATTV", SoloAttivi ? "Y" : "N"));
if (!string.IsNullOrWhiteSpace(IdIncarico))
{
query = string.Format(queryBase, "ONLY_ATTV => :ONLY_ATTV, ASSIGNMENT_ID=> :ASSIGNMENT_ID");
parameters = parameters.Append(new OracleParameter("ASSIGNMENT_ID", IdIncarico));
}
return await _context
.Set<DtoElencoIncarichi>()
.FromSqlRaw(query, parameters.ToArray())
.AsNoTracking()
.ToListAsync();
but get no results from oracle, while manually executing text from sql variable works fine, maybe parameters are not correctly replaced

Related

ef6 linq method returning $ref for nested entries in query

my linq method system from EF6 is returning $ref when I monitor results in fiddler. If I watch the local window in my webapi everything is populated correctly, but not in the actual results that are returned. It only affects the nested entries. anyone know what I am doing wrong? (I created models from database in EF6)
var student = dbEF.Accounts
.Where(x => x.AccountNumber == acctNum)
.Select(x => new DTOCrmDetails()
{
AccountNumber = x.AccountNumber,
CommissionId = x.CommissionId,
Commission = x.Commission,
ManagerID = x.ManagerID,
ManagerName = x.Manager.ManagerName,
Manager = x.Manager,
Employees = x.Manager.Employees,
WireInstructionsUSD = x.Manager.WireInstructionsUSDs
//Mapping_ManagersExecutingBrokers = x.Manager.Mapping_ManagersExecutingBrokers
}).FirstOrDefault();
return student;
these are my settings.
var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove(config.Formatters.XmlFormatter); config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
You need to disable your lazy loading in the entity framework dbcontext.
something like this way:
dbEF.Configuration.LazyLoadingEnabled = false;

LINQ to Entities does not recognize the method 'Boolean HasFlag(System.Enum)' method, and this method cannot be translated into a store expression

I have this service:
//seroiunoiweucroewr
///wercewrwerwerwer
//wcererewrwerwer
public List<UserRoleContract> GetRolePagesByUserId(long plngUserId, DisplayType displayType)
{
List<UserRoleContract> result = new List<UserRoleContract>();
using (CitiCallEntities context = new CitiCallEntities())
{
try
{
//var DisplayList = Utility.GetEnumDescriptions(typeof(DisplayType)).ToList();
//var selectValue = DisplayList.Where(i => i.Key == (byte) DisplayType.Windows).FirstOrDefault();
result = (from oUser in context.User
join oUserRole in context.UserRole on oUser.Id equals oUserRole.UserId
join oRoleRightsPage in context.RoleRightsPage.Where(i => i.IsActive == true)
on oUserRole.RoleId equals oRoleRightsPage.RoleId
join oApplicationPage in context.ApplicationPage.Where(i => i.IsActive == true)
on oRoleRightsPage.PageId equals oApplicationPage.Id
join oRole in context.Role on oUserRole.RoleId equals oRole.Id
join oEmployee in context.Employee on oUser.EmployeeId equals oEmployee.Id
join oSection in context.Section on oEmployee.SectionId equals oSection.Id
where oUser.IsActive == true && oUser.Id == plngUserId
&& oRole.IsActive == true && (((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType))
//am getting error in has flag
// am having three display type web, windows and all
// how to overcome
select new UserRoleContract
{
UserId = oUser.Id,
RoleId = oRole.Id,
RoleName = oRole.RoleName,
PageID = oApplicationPage.Id,
PageName = oApplicationPage.PageName,
IsOPsCtrl = oRole.IsOPsCtrl,
ISOPsCtrlFor = oRole.OPsCtrlFor,
SectionId = oSection.Id,
DisplayType = oRoleRightsPage.DisplayType,
}).Distinct().ToList();
}
catch (Exception exception)
{
HandleExpcetion(exception);
//throw new CitiCallException(exception.Message);
}
}
return result;
}
I am getting Linq error in has flag conversion, how do I overcome this problem?
you are geeting error because HasFlag method is not paresent in database i.e. it might be part of language or local function in code which is not present in database.
So when query is translated it found this method is not available and that is the reason you are getting error.
one solution to avoid this error is
Brind all data from databae
Than filter than data, i.e. apply HasFlag method of it.
But this will bring all data and might decrease performance.
Example is
remove this line (((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType) from your query
var list = querieddata //first fetch data without hasflag condition/method
.AsEnumerable() // Rest of the query in-process
.Where(oRoleRightsPage=> ((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType))//apply condition here once fetching done
.ToList();
The HasFlag method has no equivalent in Linq to Entities which is why you get that error. You can get around it by using bitwise comparison instead of using HasFlag, for example this:
((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType)
Becomes:
(oRoleRightsPage.DisplayType & displayType) > 0

Only primitive types ('such as Int32, String, and Guid') are supported in this context when I try updating my viewmodel

I am having some trouble with a linq query I am trying to write.
I am trying to use the repository pattern without to much luck. Basically I have a list of transactions and a 2nd list which contains the description field that maps against a field in my case StoreItemID
public static IList<TransactionViewModel> All()
{
var result = (IList<TransactionViewModel>)HttpContext.Current.Session["Transactions"];
if (result == null)
{
var rewardTypes = BusinessItemRepository.GetItemTypes(StoreID);
HttpContext.Current.Session["Transactions"] =
result =
(from item in new MyEntities().TransactionEntries
select new TransactionViewModel()
{
ItemDescription = itemTypes.FirstOrDefault(r=>r.StoreItemID==item.StoreItemID).ItemDescription,
TransactionDate = item.PurchaseDate.Value,
TransactionAmount = item.TransactionAmount.Value,
}).ToList();
}
return result;
}
public static List<BusinessItemViewModel>GetItemTypes(int storeID)
{
var result = (List<BusinessItemViewModel>)HttpContext.Current.Session["ItemTypes"];
if (result == null)
{
HttpContext.Current.Session["ItemTypes"] = result =
(from items in new MyEntities().StoreItems
where items.IsDeleted == false && items.StoreID == storeID
select new BusinessItemViewModel()
{
ItemDescription = items.Description,
StoreID = items.StoreID,
StoreItemID = items.StoreItemID
}).ToList();
}
return result;
However I get this error
Unable to create a constant value of type 'MyMVC.ViewModels.BusinessItemViewModel'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
I know its this line of code as if I comment it out it works ok
ItemDescription = itemTypes.FirstOrDefault(r=>r.StoreItemID==item.StoreItemID).ItemDescription,
How can I map ItemDescription against my list of itemTypes?
Any help would be great :)
This line has a problem:
ItemDescription = itemTypes.FirstOrDefault(r=>r.StoreItemID==item.StoreItemID)
.ItemDescription,
Since you are using FirstOrDefault you will get null as default value for a reference type if there is no item that satifies the condition, then you'd get an exception when trying to access ItemDescription - either use First() if there always will be at least one match or check and define a default property value for ItemDescription to use if there is none:
ItemDescription = itemTypes.Any(r=>r.StoreItemID==item.StoreItemID)
? itemTypes.First(r=>r.StoreItemID==item.StoreItemID)
.ItemDescription
: "My Default",
If itemTypes is IEnumerable then it can't be used in your query (which is what the error message is telling you), because the query provider doesn't know what to do with it. So assuming the that itemTypes is based on a table in the same db as TransactionEntities, then you can use a join to achieve the same goal:
using (var entities = new MyEntities())
{
HttpContext.Current.Session["Transactions"] = result =
(from item in new entities.TransactionEntries
join itemType in entities.ItemTypes on item.StoreItemID equals itemType.StoreItemID
select new TransactionViewModel()
{
ItemDescription = itemType.ItemDescription,
TransactionDate = item.PurchaseDate.Value,
TransactionAmount = item.TransactionAmount.Value,
CustomerName = rewards.CardID//TODO: Get customer name
}).ToList();
}
I don't know the structure of your database, but hopefully you get the idea.
I had this error due a nullable integer in my LINQ query.
Adding a check within my query it solved my problem.
query with problem:
var x = entities.MyObjects.FirstOrDefault(s => s.Obj_Id.Equals(y.OBJ_ID));
query with problem solved:
var x = entities.MyObjects.FirstOrDefault(s => s.Obj_Id.HasValue && s.Obj_Id.Value.Equals(y.OBJ_ID));

Using LINQ to pull MembershipUser.Username into a new object

I have the following code and I need to pull out each user's username from the membership tables:
var results = (from u in db.U_USER
where u.Forename.ToLower().Contains(search)
|| u.Surname.ToLower().Contains(search)
select new ExUser
{
MembershipId = u.MembershipId,
Surname = u.Surname,
Forename = u.Forename,
Username = Membership.GetUser(u.MembershipId).UserName
});
Now I know why im getting the following, but can anybody recommend a solution?
LINQ to Entities does not recognize the method 'System.Web.Security.MembershipUser GetUser
LINQ to Entities is trying to translate your select expression into T-SQL, which it can't because there's no ExUser etc. in T-SQL.
Finhish off the expression with a call to AsEnumerable or similar, and then perform the projection:
var results = (from u in db.U_USER
where u.Forename.ToLower().Contains(search)
|| u.Surname.ToLower().Contains(search)
select u)
.AsEnumerable()
.Select(u => new ExUser
{
MembershipId = u.MembershipId,
Surname = u.Surname,
Forename = u.Forename,
Username = Membership.GetUser(u.MembershipId).UserName
});
You can do it by forcing the results into memory by using AsEnumerable. When the results are in memory you can call Membership.GetUser without linq attempting to translate it to sql:
var results = (from u in db.U_USER
where u.Forename.ToLower().Contains(search) || u.Surname.ToLower().Contains(search)
).AsEnumerable().Select(u => new ExUser {
MembershipId = u.MembershipId,
Surname = u.Surname,
Forename = u.Forename,
Username = Membership.GetUser(u.MembershipId).UserName
});

How to make IQueryable<out T> work with a reqular IQueryable?

I am using Linq2SQL and working with a legacy system. The system was built in .Net but without a datalayer so I am transcoding it so that it will have one. I have a linq query that looks like this...
var data = from p in db.tblPeoples
orderby p.strLastName,p.strFirstName
select new
{
guidPersonId = p.guidPersonId,
strFirstName = p.strFirstName,
strLastName = p.strLastName,
strRank = p.tblCodesRank.strDescription,
strPhone = p.strPhone,
strEmail = p.strEmail,
strOffice = p.tblOrganization.strAcronym,
RolesList = p.tblRoles
};
and when I check the signature of the var it is an IQueryable and I have no idea what that is. In my datalayer I have this returning as an IQueryable, but when I try to use the datalayer version and then do a .where on the returned dataset to search on it, I get errors that I Cannot convert lambda expresstion to type 'string' because it is not a delegate type.
What should I do about this? I am trying to create code reuse and use my datalayer version that is already written. the data layer version looks like this:
public static IQueryable RetrieveAllPeople()
{
var data = from p in db.tblPeoples
orderby p.strLastName, p.strFirstName
select new
{
guidPersonId = p.guidPersonId,
strFirstName = p.strFirstName,
strLastName = p.strLastName,
strRank = p.tblCodesRank.strDescription,
strPhone = p.strPhone,
strEmail = p.strEmail,
strOffice = p.tblOrganization.strAcronym,
RolesList = p.tblRoles
};
return data;
}
Your return type should be IQueryable<T>, which is not the same as IQueryable.
To do so, you need to create a class to fill in your select instead of using an anonymous one like you do.

Resources