My app is EF 5.0 Code First using DbContext. I've been trying to manipulate (filter & sort) using Linq. I'm first trying to load a context to Local like:
context.mytable.orderby(function a a.somestring).thenby(function b d.someint).load
I don't get any error but the string ordering is ignored. The int sort works. Similarly when I try to set my binding source the linq portions comparing strings or dates doesn't work but when I use integers it works. I assume these are not converting to SQL query correctly but I can't figure out how to fix them. I would appreciate a point in the right direction.
Load() however doesn't create anything, it only takes a bunch of items and loads them from the underlying source to your context. You can't impose ordering on context.mytable because mytable doesn't hold the actual data, it holds part of the query you'll be using to get the actual data.
To get ordering to your UI you need to either order the list you'll be binding to, or use an unordered list and wrap it in an object whose job is to apply ordering. Since you're using Local go with the later and use CollectionViewSource.
Here's an example of CollectionViewSource in WPF. It's bound to the property StateOrProvinces of the DataContext that is the unordered list I want displayed in order:
<UserControl.Resources>
<CollectionViewSource x:Key="stateOrProvinceViewSource" Source="{Binding Path=StateOrProvinces}" >
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Name" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</UserControl.Resources>
with scm being:
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
The same thing in code:
CollectionViewSource orderedView = new CollectionViewSource()
{
Source = StateOrProvinces,
};
orderedView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
Using an extra layer to apply ordering has a few advantages. It lets you display the same list with different ordering in different places and you add/remove items from the underlying list without having to manually apply ordering every time.
You should also look at CollectionView class that has some extra bells and whistles but I wont go into it, to cut down on info overload.
Related
I would like to know how I can convert elements of a column of a DataTable to a list of type string, grouping the elements to avoid repetition.
For example my DataTable would look like this
DataTable
and I want to make a list containing the elements of only "User" without repeating itself using LINQ.
The code I was trying to use is
InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString).ToList(Function(g) g.ToList())
But it doesn't work for me since I am new to LINQ and still have problems forming the structures.
I'd use this:
InvoiceList = InvoiceDT.AsEnumerable().Select(Function(r) r("User").ToString()).Distinct().ToList()
If you wanted a GroupBy solution it's
InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString()).Select(Function(g) g.Key).ToList()
Where your code went wrong was in trying to pass a delegate to ToList; it doesn't take one (and you wouldn't ToList the g either, as it's a list of data rows with all varying properties).
To reshape our IGrouping (something like a list of objects that all share the same Key, which is a property of the list that the IGrouping represents) produced by the groupby into a sequence of string Keys we Select the Key, and then ToList that
There is a lot of back and forthing between developers over things like ToList vs ToArray - some people universally use ToList because, for collections of an unknown number of elements, both list and array will grow and resize repeatedly in the same way but using ToArray requires one additional resizing step at the end to trim off any unused slots. Mostly that's trivial in terms of an overall performance consideration and should be weighed against the benefit of releasing the memory with the trim. Getting into finer details is way beyond the scope of this answer but you can read some huge blog posts about it.
I personally think it's more important to generate sensible code by calling the method that results in the relevant type depending on what you plan to do with it; I ToList if I need List functionality (add/insert/remove).. I prefer ToArray if an array suits the follow-on purposes (read/write/random access, no insert or delete), and if I'll only ever enumerate it I don't To... anything at all - I just ForEach the result of the query, which can give a bigger performance boost than anything else because it means I may not have to enumerate the entire set (if I stop early) or allocate memory all at once for doing so (if I'm writing to a socket or file)
On the use of ToString; it's worth avoiding if you think you'll fall into a pattern where you do it on every column just to get a string. If the column is already a string it's an acceptable way to get the object that DataRow.Item gives you, into a string. If the column is another type it's better to cast it:
DirectCast(r("Age"), Integer)
r.Field(Of Integer)("Age")
Thing is, it's verbose, and ugly, and intellisense doesn't help you out with writing Age or knowing it's an Int. LINQ in VB is bad enough for verbosity without pouring gas on that fire. If you're working with datatables of a known structure, it's a lot nicer if you make strongly typed ones:
Add a new file of type DataSet to your project
Open it so the design surface appears. In the properties grid call it something reasonable, such as AccountsDataSet
Right click, Add Table, call it Invoices
Right click the emppty table, Add Column, call it User
Then use it like:
Dim dt as new AccountsDataSet.InvoicesDataTable
Populate it like:
dt.AddInvoicesRow("John Smith", ... other properties here)
Query it like:
dt.Select(Function(r) r.User).Distinct()
Much nicer than accessing column names by string, and having them be objects that need casting..
Consider the dataset generator as a way to quickly, visually, create poco classes with named, typed properties
Try this
dim list as List(of string) = InvoiceDT.Rows.
Cast(of DataRow)().
Select(Function(r) r("User").ToString()).
Distinct().
ToList()
Here you cast Row collection as IEnumerable(of DataRow), rest is trivial
As far as I understand, it is not possible in Appian to dynamically construct (process) variable names, just like you would do e.g. with bash using backticks like MY_OBJECT=pv!MY_CONS_`extract(valueOfPulldown)`. Is that correct? Is there a workaround?
I have set of Appian constants, let's call them MY_CONS_FOO, MY_CONS_BAR, MY_CONS_LALA, all of which are e.g. refering to an Appian data store entity. I would like to write an Appian expression rule which populates another variable MY_OBJECT of the same type (here: data store entity), depending e.g. of the options of a pull-down menu having the possible options stored in an array MY_CONS_OPTIONS looking as follows
FOO
BAR
LALA
I could of course build a lengthy case-structure which I have to maintain in addition to MY_CONS_OPTIONS, so I am searching for a more dynanmic approach using the extract() function depending on valueOfPulldown as the chosen value of the pulldown-menu.
Edit: Here the expression-rule (in pseudo-code) I want to avoid:
if (valueOfPulldown = 'FOO') then MY_OBJECT=pv!MY_CONS_FOO
if (valueOfPulldown = 'BAR') then MY_OBJECT=pv!MY_CONS_BAR
if (valueOfPulldown = 'LALA') then MY_OBJECT=pv!MY_CONS_LALA
The goal is to be able to change the data store entity via pulldown-menu.
This can help you find what is behind your constant.
fn!typeName(fn!typeOf(cons!YOUR_CONSTANT)).
Having in mind additional details I would do as follows:
Create separate expression that will combine details into list of Dictionary like below:
Expression results (er):
{
{dd_label: "label1", dd_value: 1, cons: "cons!YOUR_CONSTANT1" }
,{dd_label: "label2", dd_value: 2, cons: "cons!YOUR_CONSTANT2" }
}
on UI for your dropdown control use er.dd_label as choiceLabels and er.dd_value as choiceValues
when user selects value on Dropdown save dropdown value to some local variable and then use it to find your const by doing:
property( index(er, wherecontains(local!dropdownselectedvalue, tointeger(er.dd_value))), "cons")
returned value of step 3 is your constant
This might not be perfect as you still have to maintain your dictionary but you can avoid long if...else statements.
As a alternative have a look on Decisions Tables in Appian https://docs.appian.com/suite/help/21.1/Appian_Decisions.html
I'm using odoo 8 in my class I use a field selection but when I use it in the view XML with the widget statusbar the values are all in not order (all mess up) it is showing me the values in the statusbar first cancel, then new, then confirm all in disorder why is doing this?
this is my code in the class
'state': fields.selection ({('new','Nueva'),
('draft','Asignada'),
('cancel','Cancelada'),
('sent','Revisada'),
('confirmed','Atendiendose'),
('done','Liberada'),
('agent','Agendada')},
'Estatus Orden')
in the view xml i only worte this:
field name="state" widget="statusbar"
I don't know how to order correctly because the bar shows the list in not order does anybody know?
You can arrange the sequence of the state. You can add state to status bar in the following way
<field name="state" widget="statusbar" statusbar_visible="new,draft,confirmed,cancel" />
You need to replace {} in fields.selection by [].
Because there is huge difference between set {} and list [].
Set :
The sets module provides classes for constructing and manipulating unordered collections of unique elements. Common uses include membership testing, removing duplicates from a sequence, and computing standard math operations on sets such as intersection, union, difference, and symmetric difference.
Refer more about Set
List :
Lists are are really variable-length arrays, not Lisp-style linked lists. The list type is a container that holds a number of other objects, in a given order (Ordered Collection). The list type implements the sequence protocol, and also allows you to add and remove objects from the sequence.
Refer more about List
Field definition :
'state': fields.selection ([('new','Nueva'), ('draft','Asignada'), ('cancel','Cancelada'), ('sent','Revisada'), ('confirmed','Atendiendose'), ('done','Liberada'), ('agent','Agendada')], 'Estatus Orden')
Difference between Set and List
Sets and Lists in Python
In Python, when to use a Dictionary, List or Set?
We had the following code to retrieve data of type TYPE through a model, which is a custom proxy model. This is required by the next QSortFilterProxyModel to make the decision about filtering of elements. The code is actually combined from 2 functions: in the project we usually have some arbitrary index related to some ROW and use it to retrive the data from another predefined column which contains TYPE data.
QModelIndex index = sourceModel()->index(row, COLUMN1, sourceParent); /* sourceParent is always'invalid' - retrieving data from top-level items*/
ModelIndex sibling = index.sibling(row, COLUMN2);
return sibling.data(Qt::EditRole).value<TYPE>();
This worked fine with Qt4 but when moved to Qt5 sibling became 'invalid'. I wonder what has happened, taking into account that the data is actually there, which I see, by changing the code to the following
return sourceModel()->index(sourceRow, COLUMN2, sourceParent).data(Qt::EditRole).value<TYPE>();
-works fine
Looking at the implementation of sibling(), I cannot tell what makes it return an invalid index in your case. Comparing with the Qt4 implementation, maybe it's around the IndexMap use.
But why don't you simply use your solution with sourceModel()->index(sourceRow, COLUMN2, sourceParent), since it already seems to be what you actually want to do?
I have the following selection parameter:
PARAMETERS: p_ver(2) AS LISTBOX VISIBLE LENGTH 5.
I would like to populate it with the results from a ZECONFIG_VAR table.
At what point would I do this. Selection Screen Output, Start of Selection, or other. I am trying to allow users the ability to decide what version of the web service they would like to call. The config table will have different url's for the different versions.
I have looked at this Answer and the tutorial provided does not make sense to me.
I would do it at the event INITIALIZATION
However, it may be even easier to just create a search-help, and assign it to p_ver using the following:
parameters: p_ver(2) visible lenghth 5 MATCHCODE OBJECT zshelpname.
Esti is right that you probably want to fill an internal table from the DB table during INITIALIZATION.
But to the populate the listbox parameter, you need to put the call to VRM_SET_VALUES in AT SELECTION-SCREEN OUTPUT.