Linq query to return boolean - c#-4.0

I am inserting data into my entity table using .AddObject(). The object is of the entity table's type. The object is eventStudent, it has string eventStudent.ID, bool eventStudent.StudentPresent, bool eventStudent.ParentPresent.
The students are a list of strings containing student ids. Their presence at the event is in another object called attendees, consisting of String studentID, bool studentPresent and bool parentPresent. Only student id's that have true for StudentPresent and/or ParentPresent are in the attendees list.
As I load up my eventStudent object, I need to set StudentPresent and ParentPresent. This is what I came up with:
foreach (StudentMinimum student in students)
{
eventStudent.StudentPresent = (from a in attendees
where a.StudentID.Contains(student.StudentID)
&& a.StudentPresent
select a.StudentPresent);
}
I receive the error cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'bool'
How can I improve my query so eventStudent.StudentPresent is set to either True or False?

The compiler doesn't know what type will be returned from your query as you haven't explicitly casted it to a type. As a result, it gets a generic IEnumerable type (there could be many records returned right? Hence the IEnumerable. And those records could each be of any type, hence the generic type).
So if the data in your DB were bad and you got multiple records back, converting:
StudentPresent
true
false
false
to a bool is not going to happen. There are a few ways you could get around this. Personally, I'd do something like
var studentPresent = (from a in attendees
where a.StudentID.Contains(student.StudentID)
&& a.StudentPresent
select a.StudentPresent).FirstOrDefault();
eventStudent.StudentPresent = (bool)studentPresent;
Well, actually, I'd use a lambda query instead but that's just personal preference.

Related

How to use BQL In Operator with Select2 query / PXProjection and list of values

I am trying to replicate the following type of SQL query that you can perform in SQL Server...the important part here is the WHERE clause:
Select InventoryCD from InventoryItem WHERE InventoryCD IN ('123123', '154677', '445899', '998766')
It works perfectly using the IN3<> operator and a series of string constants:
i.e. And<InventoryItem.inventoryCD, In3<constantA,constantB,constantC>,
However, I need to be able to do this with an arbitrarily long list of values in an array, and I need to be able to set the values dynamically at runtime.
I'm not sure what type I need to pass in to the IN<> statement in my PXProjection query. I have been playing around with the following approach, but this throws a compiler error.
public class SOSiteStatusFilterExt : PXCacheExtension<SOSiteStatusFilter>
{
public static bool IsActive()
{
return true;
}
public abstract class searchitemsarray : PX.Data.IBqlField
{
}
[PXUnboundDefault()]
public virtual string[] Searchitemsarray { get; set; }
}
I think maybe I need an array of PXString objects? I'm really not sure, and there isn't any documentation that is helpful. Can anyone help?
This shows how to do it with a regular PXSelect: https://asiablog.acumatica.com/2017/11/sql-in-operator-in-bql.html
But I need to be able to pass in the correct type using Select2...
For reference I will post here the example mentioned by Hugues in the comments.
If you need to generate a query with an arbitrary list of values generated at runtime like this:
Select * from InventoryItem InventoryItem
Where InventoryItem.InventoryCD IN ('123123', '154677', '445899', '998766')
Order by InventoryItem.InventoryCD
You would write something like this:
Object[] values = new String[] { "123123", "154677", "445899", "998766" };
InventoryItem item = PXSelect<InventoryItem,
Where<InventoryItem.inventoryCD,
In<Required<InventoryItem.inventoryCD>>>>.Select(Base, values);
Please note that In<> operator is available only with Required<> parameter and you need to pass array of possible values manually to Select(…) method parameters. So you need to fill this array with your list before calling the Select method.
Also, the Required<> parameter should be used only in the BQL statements that are directly executed in the application code. The data views that are queried from the UI will not work if they contain Required<> parameters.
I ended up creating 100 variables and using the BQL OR operator, i.e.
And2<Where<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter1>>,
Or<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter2>>,
Or<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter3>>,
Or<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter4>>,
etc...etc...
You can then set the value of Pagefilter1, 2, etc inside of the FieldSelecting event for SOSiteStatusFilter.inventory, as an example. The key insight here, which isn't that obvious to the uninitiated in Acumatica, is that all variables parameterized in SQL Server via BQL are nullable. If the variable is null when the query is run, SQL Server automatically disables that variable using a "bit flipping" approach to disable that variable in the SQL procedure call. In normal T-SQL, this would throw an error. But Acumatica's framework handles the case of a NULL field equality by disabling that variable inside the SQL procedure before the equality is evaluated.
Performance with this approach was very good, especially because we are querying on an indexed key field (InventoryCD isn't technically the primary key but it is basically a close second).

How to find the string from string array in firestore

I have a list of documents and each document has a field of a string array named "fav", it has more than 50k emails, there are almost 1000 documents and in each document's "fav" array has variable length including 50k, 20k,10, etc. I was fetching all documents
Firestore.instance.collection("save").snapshots();
through StreamBuilder
StreamBuilder(
stream: Firestore.instance.collection("save").snapshots();,
builder: (context, snapshot) {
if (!snapshot.hasData)
return Text("Loading Data.............");
else {
listdata = snapshot.data.documents;
return _buildBody(snapshot.data.documents);
}
},
)
Now How I can search my required email from each document's field "fav"? I have to perform an operation after finding the required id in the array locally.
The question is not very clear, but for my understanding, this is what you are looking for
Firestore.instance.collection('save')
.where('fav', arrayContains: 'abc#gmail.com').snapshots()
The question is not very clear, but for my understanding, you want to find one e-mail in the array field. This array is contained on each document, and all the documents are "streamed" in a collection of snapshots.
Contains Method: https://api.dartlang.org/stable/2.0.0/dart-core/Iterable/contains.html
bool contains (
Object element
)
Returns true if the collection contains an element equal to element.
This operation will check each element in order for being equal to element, unless it has a more efficient way to find an element equal to element.
The equality used to determine whether element is equal to an element of the iterable defaults to the Object.== of the element.
Some types of iterable may have a different equality used for its elements. For example, a Set may have a custom equality (see Set.identity) that its contains uses. Likewise the Iterable returned by a Map.keys call should use the same equality that the Map uses for keys.
Implementation
bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}

crm 2011 Any way to consistently get string value of attribute without casting?

I want to iterate thru the set of attributes for an entity and for each one, get the text value. I can do this by getting the attribute type and explicit casting but is there a way to do it regardless of type? Similar to this method...
I don't think you'll be able to simply get a text value without testing for and handling the specific field types that are possible on an entity, since some field types have more complex values where you'll need to decide what value you want to get from the field. I ran into this same situation and ended up building a function to do the heavy lifting for me. Basically I did a case statement on the attribute type and got the values I wanted based on the business needs, here's an example of the function I used:
Private Function GetAttributeValue(ByRef pEntity As Entity, ByRef pAttr As KeyValuePair(Of String, Object)) As String
Dim lstrValue As String = String.Empty
Select Case pAttr.Value.GetType
Case GetType(OptionSetValue)
lstrValue = String.Format("{0} - {1}", CType(pAttr.Value, OptionSetValue).Value.ToString(), pEntity.FormattedValues(pAttr.Key))
Case GetType(EntityReference)
lstrValue = CType(pAttr.Value, EntityReference).Id.ToString()
'... could also get the Name value from the EntityReference
Case GetType(Money)
lstrValue = CType(pAttr.Value, Money).Value.ToString()
Case GetType(Date)
lstrValue = CType(pAttr.Value, Date).ToString("MM/dd/yy hh:mm:ss")
Case GetType(Guid)
lstrValue = CType(pAttr.Value, Guid).ToString()
Case Else
'... assume a string and just return the attribute value, or do some other handling
End Select
Return lstrValue
End Function
Once I had this function, I could just iterate through the attributes on the entity I was dealing with and get some text value back that represented the value for each field regardless of the field type. One thing to note, in my example I'm getting the string value of OptionSet fields using .FormattedValues(), I believe you can only use that if your entities have the Id unique identifier field populated.
you can use the method GetFormattedAttributeValue of the Entity class.
Example:
Entity myAccount = service.Retrieve("account", accountId, new ColumnSet(true));
string createdOn = myAccount.GetFormattedAttributeValue("createdon");

Checking for Null Values in CRM 2011 Custom Workflow Activity

I am trying to perform some logic in a CRM 2011 Custom Workflow Activity with some attributes from the calling entity. I am having an issue with determining whether a particular attribute is null or not. I have tried seemingly all combinations of GetAttributeValue and the Attributes collection, but it seems that I will always get either a Specified Cast is not Valid or Object Reference Not Set to an Instance of an Object error when there is a null value for an attribute I'm trying to access. Does anyone know the correct method for accessing an attribute that may be null? In this example, I am working with attributes of the Guid/Entity Reference type.
You can always check to see if the attributes collection contains the specific attribute that you're looking for, but you shouldn't even have to do that. All Non-nullable types (Guid, DateTime, etc) are stored as nullable types in the Attributes collection and that's probably your problem. Try something like this ( assuming late bound):
var isValid = entity.GetAttributeValue<bool?>("new_IsValid");
CRM never returns a non-nullable value. Even things that you think would be null (bool, DateTime, int, etc) are returned as their nullable equivalent. A non-nullable cast will still succeed if the value is not null, but if the value is null, it'll give you a null reference error;
object a = new bool?(true);
bool value = ((bool)a); // Works
object b = new bool?();
bool value = ((bool)b); // Null Ref Error
This syntax ended up working for me:
//if current outside counsel not null, grab GUID value
if (thisCase.lgl_outsidecounselid != null)
{
currentOCGUID = thisCase.lgl_outsidecounselid.Id;
}
//it's null, set Guid to Guid.empty
else
{
currentOCGUID = Guid.Empty;
}

Casting to types that are know only at Runtime by their string names. C#

I've got a problem here. (C#)
There's a collection in another assembly (I cannot change it) that takes a string as parameter and returns an object.
Like:
object Value = ThatCollection.GetValue("ParameterName");
The problem is, for each parameter string, it returns a DIFFERENT type as object.
What I want is to cast those objects to their respective types, knowing the types only at runtime by their string names.
I need to do some operations with those returned values.
And for that I need to cast them properly in order to access their members and so.
Limitations:
I cannot use "dynamic" since my code needs to be done in an older framework: 3.5 (because of interop issues).
I need to do operations with MANY returned values of different types (no common interfaces nor base classes, except "object", of course)
All I have is a table (containing string values) correlating the parameter names with their returned types.
Yes, I could transform that table into a biiig "switch" statement, not very nice, don't want that.
Any hints??
You want to look into reflection, something like the following should work to cast an object to type T. Set up a simple cast method:
public static T CastToType<T>(object o)
{
return (T)o;
}
Invoke this using reflection:
Type t = Type.GetType(stringName)
MethodInfo castTypeMethod = this.GetType().GetMethod("CastToType").MakeGenericMethod(t);
object castedObject = castTypeMethod .Invoke(null, new object[] { obj });

Resources