SubSonic How to provide a column name in a generic method - subsonic

Using SubSonic3, I have this generic method (thanks to linq guy, James Curran):
public List<T> GetFromList<T>( List<Guid> _IDs,
Func<T, Guid> GetID,
Func<IQueryable<T>> GetAll )
where T : class, IActiveRecord
{
List<T> rc = null;
var Results =
from item in GetAll( )
where ( _IDs as IEnumerable<Guid> ).Contains( GetID( item ) )
select item;
rc = Results.ToList<T>( );
return rc;
}
It is called with something like
List<Job> jresults = GetFromList( IDList,
item => item.JobID,
( ) => Job.All( ) );
Where IDList is a List of guids that are keys to the table.
When not generic, the linq looks like this and works perfectly. I was quite impressed that SubSonic's linq provider could take this code and turn it into SELECT * FROM Job WHERE JobID IN (a, b, c):
var Results =
from item in Job.All( )
where ( _IDs as IEnumerable<Guid> ).Contains( item.JobID )
select item;
I want to be able to call this method on tables other than Job, with keys other than JobID. The GetAll Func works because it returns the same IQueryable that Job.All( ) does, but GetID throws a run-time exception, "LINQ expression node of type Invoke is not supported". GetID returns a value, but what I really need from it is something that Contains( item.JobID) would recognize as a column name and that the "where" syntax would accept. (I don't show it here, but I have the same problem with orderby.)
Is that possible, with what you know of SubSonic3?

My solution was to pass in the expression that Where needed:
public List<T> GetFromList( List<Guid> _IDs,
Func<IQueryable<T>> GetAll,
Expression<Func<T, bool>> _where )
where T : class, U, IActiveRecord
{
List<T> rc = new List<T>( );
if ( 0 < _IDs.Count )
{
if ( MAX_ITEMS > _IDs.Count )
{
var Results = GetAll( ).Where( _where );
rc = Results.ToList( );
}
else
{
var Results =
from id in _IDs
join item in GetAll( ) on id equals item.KeyValue( )
select item;
rc = Results.ToList( );
}
}
return rc;
}
called by
rc = GetFromList(
IDList,
( ) => Job.All( ),
( item => ( IDList as IEnumerable<Guid> ).Contains( item.JobID ) ) );

Related

Getting Gravity Forms field attributes by label text

I am working on a function to find a field from any form based on the label text. I'd like to return different attributes of the field so that I can use them later.
Originally, I just needed the value of the field, so I used the work here to return the value of a field based on the label:
function itsg_get_value_by_label( $form, $entry, $label ) {
foreach ( $form['fields'] as $field ) {
$lead_key = $field->label;
if ( strToLower( $lead_key ) == strToLower( $label ) ) {
return $entry[ $field->id ];
}
}
return false;
}
I get my value by setting a variable and passing in the field label that I'm looking for:
$mobile_phone = itsg_get_value_by_label( $form, $entry, "Mobile Phone" );
Later on, as I continued to work on my solution, I found that I also needed to find those fields and return the ID. Initially, I wrote the same function and just returned the ID, but I'd like to make the solution more efficient by rewriting the function to return multiple field attributes in an array, as such:
function get_field_atts_by_label( $form, $entry, $label ) {
foreach ( $form['fields'] as $field ) {
$lead_key = $field->label;
if ( strToLower( $lead_key ) == strToLower( $label ) ) {
$field_atts = array(
'value' => $entry[ $field->id ],
'id' => $field->id,
);
return $field_atts;
}
}
return false;
}
My problem now is that I am not quite sure how to retrieve the specific attributes from my function and set them to a variable.
Well, I'll go ahead and answer my own question. Such a simple solution to this one. Had a momentary brain fart.
$mobile_phone = get_field_atts_by_label( $form, $entry, "Mobile Phone" );
$mobile_phone_id = $mobile_phone['id'];
$mobile_phone_value = $mobile_phone['value'];

What is meant by being "physically equal" in Haxe?

I've been playing around with Neko Modules, but I think I'm getting some inconsistent behaviour.
var funcs = 0;
var objs = 0;
for (i in 0...m.globalsCount())
{
var obj:Dynamic = m.getGlobal(i);
if (Reflect.compareMethods(obj, init))
trace("matched");
if (Reflect.isFunction(obj))
funcs++;
else if (Reflect.isObject(obj))
objs++;
}
trace('Functions: $funcs');
trace('Objects: $objs');
In the above code, when I run it the first time, I get a total of 4487 functions. If I remove a function, rebuild and run, I get the expected 4486.
I added the compareMethods comparison to compare the obj with init, where init is a function I declared in the Main file, but the trace is never output.
I glanced over at the code hint for the compareMethods function, and I stumbled across the following terminology: if 'f1' and the 'f2' are **physically** equal.
Now, they are both functions, and no where in the Haxe manual does it mention anything about physical functions. So I have a two part question, really.
What is a physical function, and how do I achieve the trace result as you would expect above? Thank you, in advance.
According to haxe unit tests (and js source of Reflect) Reflect.compareMethods returns true only if you are comparing any method of the same object to itself.
// https://github.com/HaxeFoundation/haxe/blob/ff3d7fe6911ab84c370b1334d537a768a55cca56/tests/unit/src/unit/TestReflect.hx
//
// t(expr) - expr should be true
// f(expr) - expr should be false
function testCompareMethods() {
var a = new MyClass(0);
var b = new MyClass(1);
t( Reflect.compareMethods(a.add,a.add) );
f( Reflect.compareMethods(a.add,b.add) );
f( Reflect.compareMethods(a.add,a.get) );
f( Reflect.compareMethods(a.add,null) );
f( Reflect.compareMethods(null, a.add) );
/*
Comparison between a method and a closure :
Not widely supported atm to justify officiel support
var fadd : Dynamic = Reflect.field(a, "add");
var fget : Dynamic = Reflect.field(a, "get");
t( Reflect.compareMethods(fadd, fadd) );
t( Reflect.compareMethods(a.add, fadd) );
t( Reflect.compareMethods(fadd, a.add) );
f( Reflect.compareMethods(fadd, fget) );
f( Reflect.compareMethods(fadd, a.get) );
f( Reflect.compareMethods(fadd, null) );
*/
}
Also, possible use case
class Test {
static function main() {
var a = new A();
var i:I = a;
trace(Reflect.compareMethods(a.test, i.test)); //returns true
}
}
interface I
{
function test():Void;
}
class A implements I
{
public function new() {}
public function test() {}
}

Is it possible to do paging with JoinSqlBuilder?

I have a pretty normal join that I create via JoinSqlBuilder
var joinSqlBuilder = new JoinSqlBuilder<ProductWithManufacturer, Product>()
.Join<Product, Manufacturer>(sourceColumn: p => p.ManufacturerId,
destinationColumn: mf => mf.Id,
sourceTableColumnSelection: p => new { ProductId = p.Id, ProductName = p.Name },
destinationTableColumnSelection: m => new { ManufacturerId = m.Id, ManufacturerName = m.Name })
Of course, the join created by this could potentially return a lot of rows, so I want to use paging - preferably on the server-side. However, I cannot find anything in the JoinSqlBuilder which would let me do this? Am I missing something or does JoinSqlBuilder not have support for this (yet)?
If you aren't using MS SQL Server I think the following will work.
var sql = joinSqlBuilder.ToSql();
var data = this.Select<ProductWithManufacturer>(
q => q.Select(sql)
.Limit(skip,rows)
);
If you are working with MS SQL Server, it will most likely blow up on you. I am working to merge a more elegant solution similar to this into JoinSqlBuilder. The following is a quick and dirty method to accomplish what you want.
I created the following extension class:
public static class Extension
{
private static string ToSqlWithPaging<TResult, TTarget>(
this JoinSqlBuilder<TResult, TTarget> bldr,
string orderColumnName,
int limit,
int skip)
{
var sql = bldr.ToSql();
return string.Format(#"
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [{0}]) As RowNum, *
FROM (
{1}
)as InnerResult
)as RowConstrainedResult
WHERE RowNum > {2} AND RowNum <= {3}
", orderColumnName, sql, skip, skip + limit);
}
public static string ToSqlWithPaging<TResult, TTarget>(
this JoinSqlBuilder<TResult, TTarget> bldr,
Expression<Func<TResult, object>> orderSelector,
int limit,
int skip)
{
var member = orderSelector.Body as MemberExpression;
if (member == null)
throw new ArgumentException(
"TResult selector refers to a non member."
);
var propInfo = member.Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException(
"TResult selector refers to a field, it must be a property."
);
var orderSelectorName = propInfo.Name;
return ToSqlWithPaging(bldr, orderSelectorName, limit, skip);
}
}
It is applied as follows:
List<Entity> GetAllEntities(int limit, int skip)
{
var bldr = GetJoinSqlBuilderFor<Entity>();
var sql = bldr.ToSqlWithPaging(
entity => entity.Id,
limit,
skip);
return this.Db.Select<Entity>(sql);
}

How does Enumerate work in MonoTouch?

In MonoTouch I need to process each object in an NSSet. My attempt, using Enumerate, is as follows:
public override void ReturnResults ( BarcodePickerController picker, NSSet results )
{
var n = results.Count; // Debugging - value is 3
results.Enumerate( delegate( NSObject obj, ref bool stop )
{
var foundCode = ( obj as BarcodeResult ); // Executed only once, not 3 times
if ( foundCode != null )
{
controller.BarcodeScannedResult (foundCode);
}
});
// Etc
}
Although the method is invoked with three objects in results, only one object is processed in the delegate. I would have expected the delegate to be executed three times, but I must have the wrong idea of how it works.
Unable to find any documentation or examples. Any suggestion much appreciated.
You have to set the ref parameter to false. This instructs the handler to continue enumerating:
if ( foundCode != null )
{
controller.BarcodeScannedResult (foundCode);
stop = false; // inside the null check
}
Here is the ObjC equivalent from Apple documentation.
Or you could try this extension method to make it easier..
public static class MyExtensions {
public static IEnumerable<T> ItemsAs<T>(this NSSet set) where T : NSObject {
List<T> res = new List<T>();
set.Enumerate( delegate( NSObject obj, ref bool stop ) {
T item = (T)( obj ); // Executed only once, not 3 times
if ( item != null ) {
res.Add (item);
stop = false; // inside the null check
}
});
return res;
}
}
Then you can do something like:
foreach(BarcodeResult foundCode in results.ItemsAs<BarcodeResult>()) {
controller.BarcodeScannedResult (foundCode);
}
Note: Keep in mind this creates another list and copies everything to it, which is less efficient. I did this because "yield return" isn't allowed in anonymous methods, and the alternative ways I could think of to make it a real enumerator without the copy were much much more code. Most of the sets I deal with are tiny so this doesn't matter, but if you have a big set this isn't ideal.

Anonymous type and getting values out side of method scope

I am building an asp.net site in .net framework 4.0, and I am stuck at the method that supposed to call a .cs class and get the query result back here is my method call and method
1: method call form aspx.cs page:
helper cls = new helper();
var query = cls.GetQuery(GroupID,emailCap);
2: Method in helper class:
public IQueryable<VariablesForIQueryble> GetQuery(int incomingGroupID, int incomingEmailCap)
{
var ctx = new some connection_Connection();
ObjectSet<Members1> members = ctx.Members11;
ObjectSet<groupMember> groupMembers = ctx.groupMembers;
var query = from m in members
join gm in groupMembers on m.MemberID equals gm.MemID
where (gm.groupID == incomingGroupID) && (m.EmailCap == incomingEmailCap)
select new VariablesForIQueryble(m.MemberID, m.MemberFirst, m.MemberLast, m.MemberEmail, m.ValidEmail, m.EmailCap);
//select new {m.MemberID, m.MemberFirst, m.MemberLast, m.MemberEmail, m.ValidEmail, m.EmailCap};
return query ;
}
I tried the above code with IEnumerable too without any luck. This is the code for class VariablesForIQueryble:
3:Class it self for taking anonymouse type and cast it to proper types:
public class VariablesForIQueryble
{
private int _emailCap;
public int EmailCap
{
get { return _emailCap; }
set { _emailCap = value; }
}`....................................
4: and a constructor:
public VariablesForIQueryble(int memberID, string memberFirst, string memberLast, string memberEmail, int? validEmail, int? emailCap)
{
this.EmailCap = (int) emailCap;
.........................
}
I can't seem to get the query result back, first it told me anonymous type problem, I made a class after reading this: link text; and now it tells me constructors with parameters not supported. Now I am an intermediate developer, is there an easy solution to this or do I have to take my query back to the .aspx.cs page.
If you want to project to a specific type .NET type like this you will need to force the query to actually happen using either .AsEnumerable() or .ToList() and then use .Select() against linq to objects.
You could leave your original anonymous type in to specify what you want back from the database, then call .ToList() on it and then .Select(...) to reproject.
You can also clean up your code somewhat by using an Entity Association between Groups and Members using a FK association in the database. Then the query becomes a much simpler:
var result = ctx.Members11.Include("Group").Where(m => m.Group.groupID == incomingGroupID && m.EmailCap == incomingEmailCap);
You still have the issue of having to do a select to specify which columns to return and then calling .ToList() to force execution before reprojecting to your new type.
Another alternative is to create a view in your database and import that as an Entity into the Entity Designer.
Used reflection to solve the problem:
A: Query, not using custom made "VariablesForIQueryble" class any more:
//Method in helper class
public IEnumerable GetQuery(int incomingGroupID, int incomingEmailCap)
{
var ctx = new some_Connection();
ObjectSet<Members1> members = ctx.Members11;
ObjectSet<groupMember> groupMembers = ctx.groupMembers;
var query = from m in members
join gm in groupMembers on m.MemberID equals gm.MemID
where ((gm.groupID == incomingGroupID) && (m.EmailCap == incomingEmailCap)) //select m;
select new { m.MemberID, m.MemberFirst, m.MemberLast, m.MemberEmail, m.ValidEmail, m.EmailCap };
//select new VariablesForIQueryble (m.MemberID, m.MemberFirst, m.MemberLast, m.MemberEmail, m.ValidEmail, m.EmailCap);
//List<object> lst = new List<object>();
//foreach (var i in query)
//{
// lst.Add(i.MemberEmail);
//}
//return lst;
//return query.Select(x => new{x.MemberEmail,x.MemberID,x.ValidEmail,x.MemberFirst,x.MemberLast}).ToList();
return query;
}
B:Code to catch objects and conversion of those objects using reflection
helper cls = new helper();
var query = cls.GetQuery(GroupID,emailCap);
if (query != null)
{
foreach (var objRow in query)
{
System.Type type = objRow.GetType();
int memberId = (int)type.GetProperty("MemberID").GetValue(objRow, null);
string memberEmail = (string)type.GetProperty("MemberEmail").GetValue(objRow, null);
}
else
{
something else....
}

Resources