I am using Obtics library for my live-linq queries.
But I can't get pass this weird exception which makes no sense at all.
Here is my query:
var query = ExpressionObserver.Execute(() =>
from o in _orders.DefaultIfEmpty(new OrderStatusViewModel())
where o.State != OrderStateEnum.Canceled
group o by o.Isin
into g
let name = _referenceData.GetInstrumentName(g.Key)
orderby name ascending
select new ComplexRowViewModel(_referenceData)
{
UnderlyingOrder = g.First(),
PrimaryExchange = (from q in _quotes.DefaultIfEmpty(new QuoteTickViewModel()).Where(w => w.Exchange == _referenceData.GetPrimaryExchangeId(g.Key) && w.Isin == g.Key && w.Provider == ProviderEnum.Bloomberg)
select new SimpleRowViewModel()
{
UnderlyingQuote = q
}).First(),
Groupped = (from y in _orders.DefaultIfEmpty(new OrderStatusViewModel())
join x in _quotes.DefaultIfEmpty(new QuoteTickViewModel()) on new { y.Isin, y.Exchange }
equals new { x.Isin, x.Exchange }
where
y.Isin == g.Key &&
y.State != OrderStateEnum.Canceled &&
x.Provider == ProviderEnum.Tradebase &&
x.Exchange !=
_referenceData.GetPrimaryExchangeId(g.Key)
group x by new { x.Exchange }
into p
select new SimpleRowViewModel()
{
UnderlyingQuote = p.First()
}
),
Uncompressed = (from o in _orders.DefaultIfEmpty(new OrderStatusViewModel())
where o.State != OrderStateEnum.Canceled && o.Isin == g.Key
select new UncompressedRowViewModel() { UnderlyingOrder = o }),
Compressed = (from o in _orders.DefaultIfEmpty(new OrderStatusViewModel())
where o.State != OrderStateEnum.Canceled && o.Isin == g.Key
group o by new { o.LimitPrice, o.OrderSide } into x
select new CompressedRowViewModel()
{
Ask = x.Key.OrderSide == OrderSideEnum.Sell ? (decimal?)x.Key.LimitPrice : (decimal?)null,
AskSize = x.Key.OrderSide == OrderSideEnum.Sell ? x.Select(s => s.Quantity).Aggregate((c, n) => c + n) : 0,
Bid = x.Key.OrderSide == OrderSideEnum.Buy ? (decimal?)x.Key.LimitPrice : (decimal?)null,
BidSize = x.Key.OrderSide == OrderSideEnum.Buy ? x.Select(s => s.Quantity).Aggregate((c, n) => c + n) : 0,
Exchange = string.Join(", ", x.Select(s => s.Exchange)),
Isin = x.First().Isin.ToString(),
OrderBuyCount = x.Key.OrderSide == OrderSideEnum.Buy ? x.Count() : 0,
OrderSellCount = x.Key.OrderSide == OrderSideEnum.Sell ? x.Count() : 0,
RowSide = x.Key.OrderSide == OrderSideEnum.Sell ? RowSide.Sell : RowSide.Buy
})}
).Cascade();
GridData = query;
I uploaded the class which makes all this possible. http://www.4shared.com/file/ce_V8PPh/MarketData.html
The exception is:
InvalidOperationException, Added item does not appear at given index '0'.
But this makes no sense since the item is already there.
Everything works fine until an OrderStatus gets a "Cancelled" state. I think it is because I filter the cancelled orders on top of the query, but how is this relevant I don't know.
I finally found a solution to my problem. It turns out that Obtics has a problem with on the fly class creation with lambda, such as
from o in orders where o.state == "active" select new OrderModel2 {Underlying = o}
new keyword messes all up. you need handle this class creation manually.
Anyways after 2 days of head smashing I ended up having this much code.
private void CreateQueries()
{
var query = ExpressionObserver.Execute(() => (from o in _orders
where o.State != OrderStateEnum.Canceled
group o by o.Isin
into g
let name = _referenceData.GetInstrumentName(g.Key)
orderby name ascending
select GetComplexRowViewModel(
g.First()
,
(from p in _quotes
where
p.Isin == g.Key &&
p.Exchange == _referenceData.GetPrimaryExchangeId(g.Key) &&
p.Provider == ProviderEnum.Bloomberg
select GetSimpleRowViewModel(p))
,
(from q in _quotes
where
q.Isin == g.Key &&
q.Provider == ProviderEnum.Tradebase &&
g.Select(s => s.Exchange).Contains(q.Exchange)
select GetSimpleRowViewModel(q))
,
(from o in _orders
where o.Isin == g.Key
&& o.State != OrderStateEnum.Canceled
group o by new { o.LimitPrice, o.OrderSide } into x
select GetCompressedRowViewModel
(
x.Key.OrderSide == OrderSideEnum.Sell ? (decimal?)x.Key.LimitPrice : (decimal?)null,
x.Key.OrderSide == OrderSideEnum.Sell ? x.Select(s => s.Quantity).Aggregate((c, n) => c + n) : 0,
x.Key.OrderSide == OrderSideEnum.Buy ? (decimal?)x.Key.LimitPrice : (decimal?)null,
x.Key.OrderSide == OrderSideEnum.Buy ? x.Select(s => s.Quantity).Aggregate((c, n) => c + n) : 0,
string.Join(", ", x.Select(s => s.Exchange)),
x.First().Isin.ToString(),
x.Key.OrderSide == OrderSideEnum.Buy ? x.Count() : 0,
x.Key.OrderSide == OrderSideEnum.Sell ? x.Count() : 0,
x.Key.OrderSide == OrderSideEnum.Sell ? RowSide.Sell : RowSide.Buy
))
,
(from o in _orders
where o.Isin == g.Key
&& o.State != OrderStateEnum.Canceled
select GetUncompressedRowViewModel(o))
))).Cascade();
GridData = query;
}
// Obtics
private ConcurrentDictionary<string, ComplexRowViewModel> _complexRowViewModels = new ConcurrentDictionary<string, ComplexRowViewModel>();
private ComplexRowViewModel GetComplexRowViewModel(OrderStatusViewModel model, IEnumerable<SimpleRowViewModel> primaryExchanges, IEnumerable<SimpleRowViewModel> groupped
, IEnumerable<CompressedRowViewModel> compressed, IEnumerable<UncompressedRowViewModel> uncompressed)
{
if (model == null)
return _complexRowViewModels.GetOrAdd("", s2 => new ComplexRowViewModel());
return _complexRowViewModels.GetOrAdd(model.Isin,
s2 =>
new ComplexRowViewModel(_referenceData) { UnderlyingOrder = model, PrimaryExchange = primaryExchanges.DefaultIfEmpty(new SimpleRowViewModel()).First(), Groupped = groupped, Compressed = compressed, Uncompressed = uncompressed });
}
private ConcurrentDictionary<string, SimpleRowViewModel> _simpleRowViewModels = new ConcurrentDictionary<string, SimpleRowViewModel>();
private SimpleRowViewModel GetSimpleRowViewModel(QuoteTickViewModel model)
{
if (model == null)
return _simpleRowViewModels.GetOrAdd("", s2 => new SimpleRowViewModel());
return _simpleRowViewModels.GetOrAdd(model.Isin + model.Exchange,
s2 =>
new SimpleRowViewModel() { UnderlyingQuote = model });
}
private ConcurrentDictionary<string, UncompressedRowViewModel> _uncompressedRowViewModels = new ConcurrentDictionary<string, UncompressedRowViewModel>();
private UncompressedRowViewModel GetUncompressedRowViewModel(OrderStatusViewModel model)
{
if (model == null)
return _uncompressedRowViewModels.GetOrAdd("", s2 => new UncompressedRowViewModel());
return _uncompressedRowViewModels.GetOrAdd(model.InternalId,
s2 =>
new UncompressedRowViewModel() { UnderlyingOrder = model });
}
private ConcurrentDictionary<string, CompressedRowViewModel> _compressedRowViewModels = new ConcurrentDictionary<string, CompressedRowViewModel>();
private CompressedRowViewModel GetCompressedRowViewModel(decimal? Ask, int AskSize, decimal? Bid, int BidSize, string Exchange, string Isin, int OrderBuyCount, int OrderSellCount, RowSide RowSide)
{
return new CompressedRowViewModel()
{
Ask = Ask,
AskSize = AskSize,
Bid = Bid,
BidSize = BidSize,
Exchange = Exchange,
Isin = Isin,
OrderBuyCount = OrderBuyCount,
OrderSellCount = OrderSellCount,
RowSide = RowSide
};
}
It works but looks ugly, if anyone has a way to make it more beautiful I'll be appreciated.
The problem is not with the 'new' keyword but rather that two instances of type OrderModel2 are not equal even though they are created with equal construction arguments.
This can be solved in three ways:
Override the Equals method of your object.
Apply an ObticsEqualityComparerAttribute to your class with the specific equality comparer for Obtics to use.
Create a factory with a repository that returns the same object instance when called with the same construction arguments.
You seem to have used number 3, though I think your code could be more simple and generic.
Related
I have a script but it works pretty slow and Im trying to see if I could make it work faster by possibly making it loop through the columns 10,12,15,17,20,22,25,27,30,32,35,37,40,42,45,47,50,52,55,57 instead of writing an if statement for each column. The way I currently have it works but it's slow and looks like this
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Student Data-NEA" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 10 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
if( r.getColumn() == 12 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
if( r.getColumn() == 15 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
if( r.getColumn() == 17 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
Etc.
What it does is it looks at a column and if there is a P then it offsets 1 column and pastes a P- N/A. Could someone help making the script shorter so it can run faster? Thank you.
You need to use getValues(range). This way you get an array. You can process this array and then use setValues(range) to fill all cells in the range at once with values of the array. It will work much faster.
Probably something like this:
function main() {
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() != "Student Data-NEA") return;
var r = s.getActiveCell(); // current cell
var row = r.getRow(); // index of current row
var row_range = s.getRange("A"+row+":Z"+row); // get range of the row
var row_values = row_range.getValues().flat(); // get array [cell, cell, cell]
var value = "P- N/A";
// change the array (not the sheet)
if (row_values[9] == "P") row_values[10] = value;
if (row_values[11] == "P") row_values[12] = value;
if (row_values[14] == "P") row_values[15] = value;
if (row_values[16] == "P") row_values[17] = value;
// change the sheet
row_range.setValues([row_values]); // set all values for the row at once
}
If your conditions all the same, you can loop through list of columns this way:
var condition = "P";
var columns = [9, 11, 14, 16];
for (var col of columns) {
if (row_values[col] == condition) row_values[col+1] = value;
}
// instead of this
// if (row_values[9] == "P") row_values[10] = value;
// if (row_values[11] == "P") row_values[12] = value;
// if (row_values[14] == "P") row_values[15] = value;
// if (row_values[16] == "P") row_values[17] = value;
Update
I don't know why I do it, since the author of the question still provided almost no information about what he does with the table and we have no sample of the table, etc. But whatever:
If you need to change next cell to "P- N/A" (do you need it? I still have no idea) in some columns if edited cell contains "P", here is a script:
function onEdit(e) {
var s = e.source.getActiveSheet();
if (s.getName() != "Student Data-NEA") return;
var col = e.range.columnStart;
var row = e.range.rowStart;
var range = s.getRange(row,col,1,2);
var range_array = range.getValues();
var cell_value = range_array[0][0];
var next_cell_value = "P- N/A";
var cols = [10, 12, 15, 17];
if (cell_value == "P" && cols.includes(col)) {
range_array[0][1] = next_cell_value;
range.setValues(range_array);
}
}
But actually it can be done much easier and faster with standard Excel-like function (example for the cell "K1"):
=IF(EQ(J1,"P"),"P- N/A","")
Just populate with this function the columns K, M, P, R...
I cannot resolve this error.
Closing a Maintenance Request of type 'Routine Maintenance' or 'Repair' did not create of a new Maintenance Request with the correct due date. The challenge is expecting the due date to be calculated using the maintenance cycle defined on the related equipment records. If multiple equipments are used in the maintenance request, choose the shortest maintenance cycle to define the service date.
I'm having a really hard time finishing this challenge. I want to know that which part of my code is wrong, not just answer.
// TriggerHandler
public with sharing class MaintenanceRequestHelper {
public static void updateWorkOrders(Map<Id, Case> oldCases) {
// TODO: Complete the method to update workorders
Map<Id, Integer> toGetDueDateMap = new Map<Id, Integer>();
AggregateResult[] results = [SELECT Id, MIN(Maintenance_Cycle__c) minMC FROM Product2 GROUP BY Id];
for (AggregateResult ar : results) {
if (ar != null) {
toGetDueDateMap.put(ar.Id, Integer.valueOf(ar.get('minMC')));
}
}
List<Case> newCases = new List<Case>();
for (Case c : oldCases.values()) {
Case newCase = new Case();
newCase.Status = 'New';
newCase.Origin = 'web';
newCase.Vehicle__c = c.Vehicle__c;
newCase.ProductId = c.ProductId;
newCase.Type = 'Routine Maintenance';
newCase.Subject = 'Routine Maintenance';
newCase.Date_Reported__c = Date.today();
newCase.Date_Due__c = (toGetDueDateMap.get(c.Id) != null) ? Date.today().addDays(toGetDueDateMap.get(c.Id)) : Date.today();
newCases.add(newCase);
}
insert newCases;
}
}
// Trigger
trigger MaintenanceRequest on Case (after update) {
// ToDo: Call MaintenanceRequestHelper.updateWorkOrders
Map<Id, Case> caseToEvaluate = new Map<Id, Case>();
if(Trigger.isAfter && Trigger.isUpdate) {
for(Case c : Trigger.New) {
if(c.Status == 'Closed' && (c.Type == 'Repair' || c.Type == 'Routine Maintenance')) {
caseToEvaluate.put(c.Id, c);
}
}
}
MaintenanceRequestHelper.updateWorkOrders(caseToEvaluate);
}
I create correct algoritm to find less maintenance cycle days.
Try it.
newCase.Date_Due__c = Date.today() + suchEarlyDay(newMaintenanceRequest).get(cases.Id);
newCases.add(newCase);
}
}
if (newCases.size() > 0) {
insert newCases;
}
}
private static Map<Id, Integer> suchEarlyDay(List<Case> cases) {
Map<Id, Case> caseMap = new Map<Id, Case>(cases);
Map<Id, Integer> lessDate = new Map<Id, Integer>();
List<Equipment_Maintenance_Item__c> relatedList = [
SELECT Maintenance_Request__c,
Equipment__r.Maintenance_Cycle__c
FROM Equipment_Maintenance_Item__c
WHERE Maintenance_Request__c = :caseMap.keySet()
];
for (Id caseId : caseMap.keySet()) {
for (Equipment_Maintenance_Item__c equip : relatedList) {
if (!lessDate.containsKey(caseId) && caseId == equip.Maintenance_Request__c) {
lessDate.put(caseId, (Integer) equip.Equipment__r.Maintenance_Cycle__c);
} else if (lessDate.containsKey(caseId) && lessDate.get(caseId) > (Integer) equip.Equipment__r.Maintenance_Cycle__c) {
lessDate.put(caseId, (Integer) equip.Equipment__r.Maintenance_Cycle__c);
}
}
}
return lessDate;
}
This link helped me, so I modified the code like this:
public with sharing class MaintenanceRequestHelper {
public static void updateWorkOrders(List<Case> updWorkOrders, Map<Id,Case> nonUpdCaseMap) {
Set<Id> validIds = new Set<Id>();
For (Case c : updWorkOrders){
if (nonUpdCaseMap.get(c.Id).Status != 'Closed' && c.Status == 'Closed'){
if (c.Type == 'Repair' || c.Type == 'Routine Maintenance'){
validIds.add(c.Id);
}
}
}
if (!validIds.isEmpty()){
List<Case> newCases = new List<Case>();
Map<Id,Case> closedCasesM = new Map<Id,Case>([SELECT Id, Vehicle__c, ProductId, Product.Maintenance_Cycle__c,(SELECT Id,Equipment__c,Quantity__c FROM Equipment_Maintenance_Items__r)
FROM Case WHERE Id IN :validIds]);
Map<Id,Decimal> maintenanceCycles = new Map<ID,Decimal>();
AggregateResult[] results = [SELECT Maintenance_Request__c, MIN(Equipment__r.Maintenance_Cycle__c)cycle FROM Equipment_Maintenance_Item__c WHERE Maintenance_Request__c IN :ValidIds GROUP BY Maintenance_Request__c];
for (AggregateResult ar : results){
maintenanceCycles.put((Id) ar.get('Maintenance_Request__c'), (Decimal) ar.get('cycle'));
}
for(Case cc : closedCasesM.values()){
Case nc = new Case (
ParentId = cc.Id,
Status = 'New',
Subject = 'Routine Maintenance',
Type = 'Routine Maintenance',
Vehicle__c = cc.Vehicle__c,
ProductId =cc.ProductId,
Origin = 'Web',
Date_Reported__c = Date.Today()
);
If (maintenanceCycles.containskey(cc.Id)){
nc.Date_Due__c = Date.today().addDays((Integer) maintenanceCycles.get(cc.Id));
} else {
nc.Date_Due__c = Date.today().addDays((Integer) cc.Product.maintenance_Cycle__c);
}
newCases.add(nc);
}
insert newCases;
List<Equipment_Maintenance_Item__c> clonedWPs = new List<Equipment_Maintenance_Item__c>();
for (Case nc : newCases){
for (Equipment_Maintenance_Item__c wp : closedCasesM.get(nc.ParentId).Equipment_Maintenance_Items__r){
Equipment_Maintenance_Item__c wpClone = wp.clone();
wpClone.Maintenance_Request__c = nc.Id;
ClonedWPs.add(wpClone);
}
}
insert ClonedWPs;
}
}
}
And the trigger:
trigger MaintenanceRequest on Case (before update, after update) {
if(Trigger.isUpdate && Trigger.isAfter){
MaintenanceRequestHelper.updateWorkOrders(Trigger.New, Trigger.OldMap);
} }
Apex Trigger :
trigger MaintenanceRequest on Case (before update, after update) {
// ToDo: Call MaintenanceRequestHelper.updateWorkOrders
if(Trigger.isAfter && Trigger.isUpdate){
MaintenanceRequestHelper.updateWorkOrders(Trigger.new);
}
}
Apex Handler:
public with sharing class MaintenanceRequestHelper {
public static void updateWorkOrders(List<Case> existingMainReq) {
// TODO: Complete the method to update workorders
Integer count = 0;
Map<Id, Integer> toGetDueDateMap = new Map<Id, Integer>();
Map<Id,Case> newCasesToIdsMap = new Map<Id,Case>();
List<Case> createNewMainReq = new List<Case>();
List<Case> caseIdsList = new List<Case>();
Map<Equipment_Maintenance_Item__c,Id> EquipMainItemsToProdIds = new Map<Equipment_Maintenance_Item__c,Id>();
if(!existingMainReq.isEmpty()){
for(Case cc : existingMainReq){
if((cc.Type == 'Repair' || cc.Type == 'Routine Maintenance') && cc.Status == 'Closed'){
caseIdsList.add(cc);
}
}
}
List<Equipment_Maintenance_Item__c> equipMainList = [Select id,Equipment__c,Maintenance_Request__c from Equipment_Maintenance_Item__c where Maintenance_Request__c IN : caseIdsList];
if(!equipMainList.isEmpty()){
for(Equipment_Maintenance_Item__c equipMainn : equipMainList){
EquipMainItemsToProdIds.put(equipMainn,equipMainn.Equipment__c);
system.debug(EquipMainItemsToProdIds.size());
if(EquipMainItemsToProdIds.size() > 1){
count = EquipMainItemsToProdIds.size();
}
}
}
List<Equipment_Maintenance_Item__c> EMIList = [Select Equipment__r.Maintenance_Cycle__c,Equipment__c from Equipment_Maintenance_Item__c where Equipment__r.Id IN :EquipMainItemsToProdIds.values() AND Maintenance_Request__c IN:caseIdsList order By Equipment__r.Maintenance_Cycle__c ASC limit 1];
for(Equipment_Maintenance_Item__c equip : EMIList){
toGetDueDateMap.put(equip.Id,Integer.valueOf(equip.Equipment__r.Maintenance_Cycle__c));
for(Case c : caseIdsList){
Case mainRe = new Case();
mainRe.Vehicle__c = c.Vehicle__c;
mainRe.status = 'New';
mainRe.Type = 'Routine Maintenance';
mainRe.Subject = 'New Main Request For Vehicle for Apex Specialist';
mainRe.Date_Reported__c = date.today();
if(count > 1){
mainRe.Date_Due__c = Date.today().addDays(toGetDueDateMap.get(equip.Id));
}
else{
mainRe.Date_Due__c = Date.today();
}
createNewMainReq.add(mainRe);
newCasesToIdsMap.put(c.Id,mainRe);
}
insert createNewMainReq;
if(caseIdsList.size()>0 && newCasesToIdsMap.size()>0){
cloneEquipItems(caseIdsList,newCasesToIdsMap);
}
}
}
public static void cloneEquipItems(List<case> closedCaseRecords, Map<Id,case> newCreatedCasesMapp){
List<Equipment_Maintenance_Item__c> newEquipItems = new List<Equipment_Maintenance_Item__c>();
try{
if(!closedCaseRecords.isEmpty() && newCreatedCasesMapp.size()>0){
List<Equipment_Maintenance_Item__c> oldEquipItems = [SELECT Equipment__c, Maintenance_Request__c, Quantity__c,Maintenance_Request__r.Id
FROM Equipment_Maintenance_Item__c
WHERE Maintenance_Request__c IN :closedCaseRecords];
for(Equipment_Maintenance_Item__c equipItem : oldEquipItems) {
Equipment_Maintenance_Item__c newItem = equipItem.clone(false, true, false, false);
newItem.Maintenance_Request__c = newCreatedCasesMapp.get(equipItem.Maintenance_Request__c).id;
newEquipItems.add(newItem);
}
insert newEquipItems;
}
}
catch(Exception e){
System.debug('Exception is'+ e);
}
}
}
It is not hit by service and on console Failed to load resource: the server responded with a status of 500 (Internal Server Error)
http://newalturathadmin.alturath.net/api/ApiFailureDonatorMobile?currentPage=1&recordsPerPage=20&Name=&DateFrom=&DateTo=
public class ApiFailureDonatorMobileController : Application.Global.BaseControllers.ApiControllerBase
{
DateTime frmDate;
DateTime toDate;
public HttpResponseMessage Get(int currentPage, int recordsPerPage, string Name = "", string DateFrom = "", string DateTo = "")
{
try
{
var dataEntryQuery = OUnitOfWork.FailureDonatorRepository.GetAll().OrderByDescending(x => x.Id);
if (DateFrom != null || DateTo != null)
{
frmDate = DateTime.ParseExact(DateFrom, "dd-MM-yyyy", CultureInfo.InvariantCulture);
if (DateTo != null)
{
toDate = DateTime.ParseExact(DateTo, "dd-MM-yyyy", CultureInfo.InvariantCulture);
}
toDate = toDate.AddDays(1);
dataEntryQuery = dataEntryQuery.Where(x =>
(
(!string.IsNullOrEmpty(Name.Trim()) ?
(!string.IsNullOrEmpty(x.Project.ProjectName.Trim()) ? x.Project.ProjectName.Contains(Name.Trim()) : 1 == 2) : 1 == 1)
&& x.Createdon >= (string.IsNullOrEmpty(DateFrom) ? x.Createdon : frmDate.Date)
&& x.Createdon <= (string.IsNullOrEmpty(DateTo) ? x.Createdon : toDate.Date)
)).OrderByDescending(x => x.Id);
}
else
{
dataEntryQuery = dataEntryQuery.Where(x =>
(
(!string.IsNullOrEmpty(Name.Trim()) ?
(!string.IsNullOrEmpty(x.Project.ProjectName.Trim()) ? x.Project.ProjectName.Contains(Name.Trim()) : 1 == 2) : 1 == 1)
)).OrderByDescending(x => x.Id);
}
var _totalCount = dataEntryQuery.Count();
var _totalPages = Math.Ceiling((double)_totalCount / recordsPerPage);
var entries = dataEntryQuery.Skip((currentPage - 1) * recordsPerPage)
.Take(recordsPerPage)
.AsQueryable();
var includeMastersName = (from x in entries.AsEnumerable()
select new
{
Id = x.Id,
Project = x.Project_FK_ID == null ? "" : x.Project.ProjectName,
InvoiceId = x.InvoiceId,
MobileNo = x.MobileNo,
Createdon = x.Createdon,
}).AsQueryable();
var result = new
{
TotalCount = _totalCount,
TotalPages = _totalPages,
AllEntries = includeMastersName
};
return Request.CreateResponse(HttpStatusCode.OK, result);
}
catch (Exception e)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, e.Message + "-------" + e.InnerException.Message + "-------" + e.StackTrace + "-------" + e.Source); ;
}
return Request.CreateResponse(HttpStatusCode.NotFound, new { resul = "Error" });
}
}
This is my method :-
[Invoke]
public List<FamilyEvent> GetFamilyEvents(int userId)
{
List<FamilyEvent> familyEvents = new List<FamilyEvent>();
int id = -1; //just to fool ria
//this is for birthday reminders.
var qry = ((from member in this.ObjectContext.TreeMembers.Where(m => m.UserId == userId && m.Birthdate == null)
select member.TreeMemberId).Except(from item in this.ObjectContext.FamilyEvents where item.ReminderType ==
FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.BIRTHDAY_REMINDER
select item.TreeMemberId));
var mainQry = from mainMember in this.ObjectContext.TreeMembers
where qry.Contains(mainMember.TreeMemberId)
select mainMember;
foreach (var item in mainQry)
{
FamilyEvent familyEvent = new FamilyEvent
{
FamilyEventId = id--,
TreeMemberId = item.TreeMemberId,
RelatedTreeMemberId = -1,
ReminderType = FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.BIRTHDAY_REMINDER
};
familyEvent.TreeMember = item;
familyEvents.Add(familyEvent);
}
//this is for anniversary events
qry = ((from member in this.ObjectContext.TreeMembers.Where(m => m.UserId == userId && m.RelationId == (short)Relations.Partner)
select member.TreeMemberId).Except(from item in this.ObjectContext.FamilyEvents where item.ReminderType == FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.ANNIVERSARY_REMINDER
select item.TreeMemberId));
mainQry = from mainMember in this.ObjectContext.TreeMembers.Include("RelatedTreeMember")
where qry.Contains(mainMember.TreeMemberId)
select mainMember;
foreach (var item in mainQry)
{
FamilyEvent familyEvent = new FamilyEvent
{
TreeMemberId = item.TreeMemberId,
TreeMember = item,
RelatedTreeMemberId = item.RelatedTreeMemberId,
ReminderType = FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.ANNIVERSARY_REMINDER
};
familyEvent.RelatedTreeMember = item.RelatedTreeMember;
familyEvents.Add(familyEvent);
}
return familyEvents;
}
As you can see i programmatically populate the entities and populate it. When i put breakpoint on return familyEvents, i can see the correct data. However on client side, the TreeMember and RelatedTreeMember value become null. Why is it so? If i do not use [Invoke] and instead use [Query] it works, but i need Invoke in my case.
I need to implement a function for moving records up and down (sorting) and saving the sortorder with Linq to SQL. I am using SQL Server 2000 but I might be able to upgrade if there is a solution for it with a newer version of SQL Server. I would love to hear any thoughts you might have on how to do it.
Just add an integer column Index to the table and modify this index based on the user input - moving up is just decrementing the index value of the selected record and incrementing the index value of the preceding record.
public void MoveUp(Guid id)
{
Item item = Context.Items.Single(i => i.Id == id);
if (item.Index > 0)
{
Item predecessor = Context.Items.Single(i => i.Index == item.Index - 1);
item.Index -= 1;
predecessor.Index += 1;
Context.SaveChanges();
}
}
Do the opposite for moving down and you are done. If you need this for multiple tables, just create a generic version using an interface.
Thanks Daniel!
From looking at your example I came up with this for sorting products within a category.
public void MoveUp(int categoryId, int productId, int originalIndex, int newIndex)
{
if (newIndex == originalIndex) return;
var product = _context.CategoryProducts.Single(x => x.CategoryId == categoryId && x.ProductId == productId);
product.SortOrder = newIndex;
_context.CategoryProducts
.Where(x =>
x.CategoryId == categoryId &&
x.ProductId != productId &&
x.SortOrder >= newIndex &&
x.SortOrder <= originalIndex)
.Update(x => { x.SortOrder = x.SortOrder + 1; });
_context.SubmitChanges();
}
public void MoveDown(int categoryId, int productId, int originalIndex, int newIndex)
{
if (newIndex == originalIndex) return;
var product = _context.CategoryProducts.Single(x => x.CategoryId == categoryId && x.ProductId == productId);
product.SortOrder = newIndex;
_context.CategoryProducts
.Where(x =>
x.CategoryId == categoryId &&
x.ProductId != productId &&
x.SortOrder >= originalIndex &&
x.SortOrder <= newIndex)
.Update(x => { x.SortOrder = x.SortOrder - 1; });
_context.SubmitChanges();
}
I used the UpdatedExtension from Hooked on LINQ for the actual updating.