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.
Related
At this point, I'm spinning my wheels, but going nowhere and could use some help. I have an array/List of weekdays that I want to disable on my calendar using the enabledPredicateDay function. for example ['sunday', 'monday', 'tuesday'].
return TableCalendar(
calendarBuilders: CalendarBuilders(dowBuilder: (context, day) {
if (day.weekday == DateTime.sunday) {
final text = DateFormat.E().format(day);
return Center(
child: Text(
text,
style: TextStyle(color: Colors.red),
),
);
}
}),
firstDay: kFirstDay,
lastDay: kLastDay,
focusedDay: _focusedDay,
calendarFormat: _calendarFormat,
enabledDayPredicate: (date) {
// this is where we disable any days that the user is not available OR is booked up
var disabledDays = "";
unavailableDays.asMap().forEach((index, value) {
if (index == 0) {
disabledDays = disabledDays + "date.weekday != DateTime.$value";
} else {
disabledDays = disabledDays + " && date.weekday != DateTime.$value";
}
});
date.weekday != disabledDays; // here I'm trying to get some sort of boolean back.
return date.weekday != disabledDays;
}
The problem I'm running into is that I can either only return one day programmatically, let's say in a 'for in' loop, or I need to hardcode it. This is because the return value needs to be a boolean.
I tried combining everything into a string and then converting it to a method so that each day I need disabled can be the return statement like this:
return date.weekday != DateTime.$value && date.weekday != DateTime.$value && date.weekday != DateTime.$value
Everything works fine if I hardcode it like this:
return date.weekday != DateTime.sunday && date.weekday != DateTime.monday && date.weekday != DateTime.tuesday
But I haven't been able to get to this point because I'm getting a string back, but I need a bool.
How do I return multiple days to this particular function?
I figured it out...seems very hacky and maybe this can be improved. What I did here was instantiated a variable for each day. And then, as I go through the weekdays to check which is unavailable with conditional statements, I assign the weekday to the variable if and only if it's unavailable.
var unavailableDay1;
var unavailableDay2;
var unavailableDay3;
var unavailableDay4;
var unavailableDay5;
var unavailableDay6;
var unavailableDay7;
for (var day in daysOfWeek) {
// print(widget.data[day]);
if (widget.data[day] == null) {
unavailableDays.add(day);
}
}
for (var day in unavailableDays) {
if (day == "monday") {
unavailableDay1 = 1;
} else if (day == "tuesday") {
unavailableDay2 = 2;
} else if (day == "wednesday") {
unavailableDay3 = 3;
} else if (day == "thursday") {
unavailableDay4 = 4;
} else if (day == "friday") {
unavailableDay5 = 5;
} else if (day == "saturday") {
unavailableDay6 = 6;
} else if (day == "sunday") {
unavailableDay7 = 7;
}
}
Finally, I check if each of the 7 days has a value, if not null is returned. Thus, it gives me back only days that are enabled! I hope this helps someone! Please help me improve this!
enabledDayPredicate: (date) {
// this is where we disable any days that the user is not available OR is booked up
return date.weekday != unavailableDay1 &&
date.weekday != unavailableDay2 &&
date.weekday != unavailableDay3 &&
date.weekday != unavailableDay4 &&
date.weekday != unavailableDay5 &&
date.weekday != unavailableDay6 &&
date.weekday != unavailableDay7;
},
this.setState at the end of constructBoard doesn't appear to run when contructBoard is called. The function runs and works as intended other that setState not appearing to run. The callback function doesn't run either.
class Board extends Component {
state = {
layout: null
}
contructBoard = (boardSize) => {
let board = []
let boardStateLayout = {}
for (let row = 0; row < boardSize; row++) {
let temp = []
for (let column = 0; column < boardSize; column++) {
let style = null;
let key = row.toString() + column.toString()
//Top left corner
if (row === 0 && column === 0) {
style = "topLeft"
//Top right corner
} else if (row === 0 && column === boardSize - 1) {
style = "topRight"
//Bottom left corner
} else if (row === boardSize - 1 && column === 0) {
style = "bottomLeft"
//Bottom right corner
} else if (row === boardSize - 1 && column === boardSize - 1) {
style = "bottomRight"
//Top row
} else if (row === 0 && (column > 0 && column < boardSize - 1)) {
style = "topRow"
//First column
} else if (column === 0 && (row > 0 && row < boardSize - 1)) {
style = "firstColumn"
//Bottom Row
} else if (row === boardSize - 1 && (column > 0 && column < boardSize - 1)) {
style = "bottomRow"
//Last column
} else if (column === boardSize - 1 && (row > 0 && row < boardSize - 1)) {
style = "lastColumn"
} else {
style = "middle"
}
temp.push(<td key={key} onClick={this.handleSquareClick} className={style}></td>);
boardStateLayout[key] = {
showEl: false,
el: "x"
}
}
board.push(<tr key={"row" + row.toString()}>{temp}</tr>)
}
this.setState({layout: boardStateLayout}, () => console.log('set state'));
return <table className="board"><tbody>{board}</tbody></table>
}
board = this.contructBoard(3);
render() {
return (
<div className="boardContainer">
{this.board}
{/*<XorO layout={this.state.layout} />*/}
</div>
);
}
}
You're basically trying to call setState during the component's construction which React Docs discourage.
If you want to set an initial state like that you should add a constructor and assign the state directly.
Like this:
this.state = { layout: boardStateLayout }
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 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.
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.