Query a winforms control with CheckedListBoxItemCollection.AsQueryable().Provider.CreateQuery( - winforms

I need to query a winforms control(CheckedListBoxControl) having a CheckedListBoxItemCollection which I want to query for a certain Id that is within the property "Value" of the CheckedListBoxItem.
CheckedListBoxItemCollection items = myCheckedListBoxControl.Items;
foreach(Department dep in departmentList)
{
bool isDepExisting = items.AsQueryable().Where( the .Where clause does not exist );
// How can I query for the current dep.Id in the departmentList and compare this dep.Id with every Item.Value in the CheckedListBoxControl and return a bool from the result ???
if(!isDepExisting)
myCheckedListBoxControl.Items.Add( new CheckedListBoxItem(dep.id);
}
UPDATE:
IEnumberable<CheckedListBoxItem> checks = items.Cast<CheckedListBoxItem>().Where(item => item.Value.Equals(dep.InternalId));
Why says Visual Studio that the IEnumerable or the IEnumberable namespace of it can not be found? When I use "var" instead then I can compile my code. But the boss in my company forbide my to use var...

CheckListBox.Items only implements IEnumerable, not IEnumerable<T>. You get the overload of AsQueryable() that returns IQueryable (not the generic one). Which only has the Cast and OfType extension methods.
Cast the items back from object to Department. Like this:
var q = checkedListBox1.Items.Cast<Department>().AsQueryable().Where((d) => d.Id == 1);
You don't need AsQueryable() anymore btw.

Related

Dapper can't ignore nested objects for parameter?

I am beginning to use Dapper and love it so far. However as i venture further into complexity, i have ran into a big issue with it. The fact that you can pass an entire custom object as a parameter is great. However, when i add another custom object a a property, it no longer works as it tries to map the object as a SQL parameter. Is there any way to have it ignore custom objects that are properties of the main object being passed thru? Example below
public class CarMaker
{
public string Name { get; set; }
public Car Mycar { get; set; }
}
propery Name maps fine but property MyCar fails because it is a custom object. I will have to restructure my entire project if Dapper can't handle this which...well blows haha
Dapper extensions has a way to create custom maps, which allows you to ignore properties:
public class MyModelMapper : ClassMapper<MyModel>
{
public MyModelMapper()
{
//use a custom schema
Schema("not_dbo_schema");
//have a custom primary key
Map(x => x.ThePrimaryKey).Key(KeyType.Assigned);
//Use a different name property from database column
Map(x=> x.Foo).Column("Bar");
//Ignore this property entirely
Map(x=> x.SecretDataMan).Ignore();
//optional, map all other columns
AutoMap();
}
}
Here is a link
There is a much simpler solution to this problem.
If the property MyCar is not in the database, and it is probably not, then simple remove the {get;set;} and the "property" becomes a field and is automatically ignored by DapperExtensions. If you are actually storing this information in a database and it is a multi-valued property that is not serialized into a JSON or similar format, I think you are probably asking for complexity that you don't want. There is no sql equivalent of the object "Car", and the properties in your model must map to something that sql recognizes.
UPDATE:
If "Car" is part of a table in your database, then you can read it into the CarMaker object using Dapper's QueryMultiple.
I use it in this fashion:
dynamic reader = dbConnection.QueryMultiple("Request_s", param: new { id = id }, commandType: CommandType.StoredProcedure);
if (reader != null)
{
result = reader.Read<Models.Request>()[0] as Models.Request;
result.reviews = reader.Read<Models.Review>() as IEnumerable<Models.Review>;
}
The Request Class has a field as such:
public IEnumerable<Models.Review> reviews;
The stored procedure looks like this:
ALTER PROCEDURE [dbo].[Request_s]
(
#id int = null
)
AS
BEGIN
SELECT *
FROM [biospecimen].requests as bn
where bn.id=coalesce(#id, bn.id)
order by bn.id desc;
if #id is not null
begin
SELECT
*
FROM [biospecimen].reviews as bn
where bn.request_id = #id;
end
END
In the first read, Dapper ignores the field reviews, and in the second read, Dapper loads the information into the field. If a null set is returned, Dapper will load the field with a null set just like it will load the parent class with null contents.
The second select statement then reads the collection needed to complete the object, and Dapper stores the output as shown.
I have been implementing this in my Repository classes in situations where a target parent class has several child classes that are being displayed at the same time.
This prevents multiple trips to the database.
You can also use this approach when the target class is a child class and you need information about the parent class it is related to.

adding new methods to LINQ to Entities

Is there any way to define the SQL conversion component for additional functions to Linq2Entities.
For example:
myQuery.Where(entity => entity.Contains('foo', SearchFlags.All))
Ideally I am looking for something that doesn't require editing and building a new version the EntityFramework.dll directly. Is there any way to allow extension methods to entity framework that can support SQL generation.
So far I have a template which would represent the method I need to replace for LINQ to Entities:
public static bool Contains(this object source, string searchTerms, SearchFlags flags)
{
return true;
}
Of course this causes the error:
LINQ to Entities does not recognize the method 'Boolean
CONTAINS(System.Object, System.String, SearchFlags)' method, and this method
cannot be translated into a store expression.
To be clear, I don't want to do:
myQuery.AsEnumerable().Where(entity => entity.Contains('foo', SearchFlags.All))
Because I want to be able to execute code in SQL space and not return all the entities manually.
I also cannot use the .ToString() of the IQueryable and execute it manually because I need Entity Framework to populate the objects from several .Include joins.
I don't understand your Q clearly. However if your problem is that you can't use your own methods or other linq to objects method, just use .AsEnumerable() and do your other jobs through linq to objects, not L2E:
myQuery.AsEnumerable().Where(entity => entity.Contains('foo', SearchFlags.All))
And if you need to use your myQuery several times somewhere else, first load it to memory, then use it as many as you want:
var myQuery = from e in context.myEntities
select d;
myQuery.Load();
// ...
var myOtherQuery = from d in context.myEntities.Local
select d;
// Now any L2O method is supported...
I ended up doing the following (which works but is very far from perfect):
All my entities inherit from an IEntity which defines long Id { get; set; }
I then added a redundant restriction
context.myEntities.Where(entity => entity.Id != 0) this is
redundant since the identity starts at 1, but Linq2Entities doesn't
know that.
I then call .ToString() on the IQueryable after I have done all
my other queries, since it is of type DBQuery<Entity> it returns
the SQL Command Text, I do a simple replace with my query restriction.
In order to get all the .Include(...) to work I actually execute
two different sql commands. There is no other more pretty way to tap into this because of query execution plan caching causes issues otherwise (even when disabled).
As a result my code looks like this:
public IQueryable<IEntity> MyNewFunction(IQueryable<IEntity> myQueryable, string queryRestriction)
{
string rawSQL = myQueryable.Select(entity => entity.Id).ToString().Replace("[Extent1].Id <> 0", queryRestriction);
List<long> ids = // now execute rawSQL, get the list of ids;
return myQuerable.Where(entity => ids.Contains(entity.Id));
}
In short, other than manually executing the SQL or running a similar SQL command and appending the restriction using the existing commands the only way to write your own methods to Linq-to-Entities is to manually alter and build your own EntityFramework.dll from the EF6 source.

How to use predicate search with Linq-to-SQL

We are using Linq-to-SQL with SQL Server as an ORM on our new project. I have never used Linq-to-SQL before, so my question can be a bit dumb. I want to have a method that will perform a search for entities in DB by predicate, something like this:
public IEnumerable<T> Get<T>(Expression<Func<T, bool>> #where)
Could you give some advices where I can see some code samples or ideas how to implement this?
You want Where (here, originalList is any enumerable, in particular it can be a table from your context):
var filteredList = originalList.Where(element => ShouldBeIncluded(element));
Edit:
or
var filteredList =
from element in originalList
where ShouldBeIncluded(element)
select element;
And if ShouldBeIncluded is a Func<T, bool>, there's an eye-candy simplified syntax:
var filteredList = originalList.Where(ShouldBeIncluded);
Edit 2: also, note that the complete syntax is:
var filteredList = originalList.Where<TTypeOfElement>(element => ShouldBeIncluded(element));
But the generic argument can be omitted since the compiler will deduce it from the type of originalList (supposing it is an IEnumerable<TTypeOfelement>).

linq reflection WInForms

I am very new to linq and am trying to figure out how to accomplish the following:
Currently, I have a Winforms project that has a Base Form with a DataRow as one of it's members. I have several derived Forms populate the DataRow based on data from a DataTable (SQL Query Result). There are controls on the derived Forms that are populated with the values from the data as well. When the Save button on the derived Forms is clicked, the DataRow in the Base Form is updated and then the Derived Form updates the Database via a DataAdapter.
I wanted to replace all of the SQL Commands using linqs so I tried implementing this functionality using LINQ by the following:
I created my Linq query in the Derived Form and assigned the result to an Object in the Base Form. I cast the Object in the Base Form to the class type of the Linq query and use reflection to populate all the controls on the Derived Form. When the save button is clicked I update the Object but I am not able to update the Database.
The problem that I can't solve is how to update the database once the object is updated. At this point I don't have the Data Context that I used for the linq query.
I am using an SQL function within the linq query so I had to create a separate class for these values as I was getting an anonymous type error. I am probably missing something here.
Any help would be most appreciated as I really how clean the linq code is.
Edit (Copied from Brad's Edit to Tomas's answer):
Here are the 3 steps of my code.
Step 1 - Get a singe record of data from database
private void GetDatabaseDetailData()
{
_db = new PriorityDataContext();
DetailData = (from db in _db.tblDatabases
where db.DatabaseID == Id
select db).SingleOrDefault();
DeveloperData = (from db in _db.tblDatabases
where db.DatabaseID == Id
select new DeveloperInfo
{
DeveloperName = _db.func_get_employee_name(db.Developer)
}).SingleOrDefault();
}
Step 2 - Populate all controls whos name exists in the Object. The DetailData Object is cast to the specific type passed into this method. All code not shown for brevity.
protected virtual void PopulateDetailControlsA(List<Control> controlContainers, string srcDataTableName)
{
Object data = null;
Type type = null;
switch (srcDataTableName)
{
case "tblDatabases" :
type = typeof(tblDatabase);
data = (tblDatabase)DetailData;
break;
}
if (type != null)
{
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var controlContainer in controlContainers)
{
foreach (var propertyInfo in properties)
{
if (!ControlExists(controlContainer, propertyInfo.Name)) continue;
var txtControl = controlContainer.Controls[propertyInfo.Name] as ExtendedTextBox;
if (txtControl != null)
{
try
{
var value = propertyInfo.GetValue(data, null).ToString();
if (propertyInfo.Name == "row_oper_name" || propertyInfo.Name == "row_last_chng_oper_name")
{
txtControl.Text = RowOperatorData.RowOperatorName;
txtControl.ValueMember = propertyInfo.GetValue(data, null).ToString();
}
else
txtControl.Text = value;
}
catch (NullReferenceException)
{
}
continue;...........
Step 3 - Try and save changes back to database in the derived From.
private void SaveData()
{
try
{
_db.SubmitChanges();
}
catch (Exception sqlException)
{
}
}
What I am really unclear about hear is how to store the result set in the Base Form so that I can use the same code for many different queries. The DataRow worked great because I use the some code for over 25 derive Forms.
If I understand you correctly, you create the DataContext in a derived form and then use it to write some queries (in a derived form). In order to be able to update the database, your queries must return the entities obtained from the table (i.e. the select clause should just return the entity). For example:
DataContext db = // ...
var q = from p in db.Things
where p.Some > 10 select p;
If you then modify the entities, you can use db.SubmitChanges() to store the changes (made to the entity objects) to the database. For this, you need the original db value.
In your scenario, you'll need to store the DataContext (as a field) in the derived form. If you need to perform the update from the base form, then I suggest you define a virtual method:
// Base form
protected abstract void UpdateDatabase();
// Derived from with field 'db' storing 'DataContext'
protected override void UpdateDatabase() {
db.SumbitChanges();
}

How would I go about hideing a specified value from displaying in an array in a datagrid?

For example, say I have:
public var usersOnlineArray:Array = new Array(bob,jim,tim,marry,luke);
and when I put that into my datagrid like this:
buddylist.dataProvider = new DataProvider(usersOnlineArray);
buddylist.rowCount = buddylist.length;
bldBuddyList(buddylist);
How could I, let's say, prevent luke from appearing in the datagrid? Basically make him not appear but technically "still be there" so I can make him reappear later but?
I'd start by using ArrayCollection rather than Array since you can make use of data binding this way.
ArrayCollection also has a filterFunction property that will allow you to hide things but still keep them in the collection. The docs will expand on all of this but the gist is:
Make the ArrayCollection, it just takes plain ole Array in the constructor.
public var usersArr:Array = [bob, jim, tim, marry, luke];
public var usersAC:ArrayCollection = new ArrayCollection(usersArr);
Set the AC to be the data provider for the List.
buddyList.dataProvider = usersAC;
Define the filter function. This function takes an object and returns true if it should be visible, false if not.
public function myFilterFunction(o:Object):Boolean
{
if (o.toString() == "luke") return false;
return true;
}
Then apply this function to the AC.
usersAC.filterFunction = myFilterFunction;
To remove the filter simply null our the filterFunction property.
usersAC.filterFunction = null;
If you stick the array in an ArrayCollection, you can add a filter function it to. The underlying data is un-affected.

Resources