Any Way to Streamline this Logic? - entity-framework

I've written some code that translates an Entity Framework collection to some fixed fields. I ended up with the following snippet but isn't there a slicker way to accomplish this?
var numbers = c.ContactPhoneNumbers.OrderByDescending(n => n.IsPrimary);
int count = 0;
foreach (var number in numbers)
{
if (count == 0)
{
hc.PrimaryPhone = number.PhoneNumber;
hc.PrimaryPhoneType = number.PhoneNumberType;
}
else if (count == 1)
{
hc.SecondaryPhone = number.PhoneNumber;
hc.SecondaryPhoneType = number.PhoneNumberType;
}
else break;
count++;
}
c is an Entity Framework entity and c.ContactPhoneNumbers represents entries in a related table. Seems like this code could be made a little more straight forward and less awkward.

Since you are iterating the phone enumeration right away, might be better to use ToList() so you can use the indexer:
var numbers = c.ContactPhoneNumbers.OrderByDescending(n => n.IsPrimary).ToList();
if(numbers.Count > 0)
{
hc.PrimaryPhone = numbers[0].PhoneNumber;
hc.PrimaryPhoneType = number[0].PhoneNumberType;
}
if(numbers.Count > 1)
{
hc.SecondaryPhone = numbers[1].PhoneNumber;
hc.SecondaryPhoneType = numbers[1].PhoneNumberType;
}

Related

Filtering and modifying simultaneously DbSet

I'm working on the DbSet where I'm modifying it and filtering data I have modified before saving those changes to database.
Initial content of table:
Id,Name,Left,Right
1,All,1,28
2,Press,2,13
3,NewDeals,3,4
4,Contracts,5,6
5,People,7,12
6,Promotions,8,9
7,Deaths,10,11,
8,Finanse,14,19
9,Results,15,16,
10,Stocks,17,18
11,Stories,20,25
12,SuccessStories,21,22,
13,LearnStories,23,24
14,AccessToEverything,26,27
Steps looks like this:
//items are DbSet
var nodeLeft = 10;
var nodeRight = 11;
var parentNodeRight = 28;
var size = 2;
var itemsToUpdate = items.Where(i => i.Left >= nodeLeft && i.Right <= nodeRight);
foreach (var item in itemsToUpdate)
{
item.Left = 0 - item.Left;
item.Right = 0 - item.Right;
}
// step 2
itemsToUpdate = items.Where(i => i.Left > nodeRight);
foreach (var item in itemsToUpdate)
{
item.Left = item.Left - size;
}
itemsToUpdate = items.Where(i => i.Right > nodeRight);
foreach (var item in itemsToUpdate)
{
item.Right = item.Right - size;
}
//step 3
itemsToUpdate =
items.Where(i => i.Left >= (parentNodeRight > nodeRight ? parentNodeRight - size : parentNodeRight));
foreach (var item in itemsToUpdate)
{
item.Left = item.Left + size;
}
At step 3, where statement is returning values which does not fulfill the statement in where.
It looks like EF is filtering the data which are not in memory but in DB.
If I change items to regular list by applying toList() everything is working fine.
I would really like to avoid that since data set I'm working on can be very big and I can not initially pre-filter it.
Could you please advise what I'm missing / doing wrong here ?

Result not ready when used, works in debugger but not in runtime

In the following image you can see where i put the breakpoint and then debugged two step. You can also see that both assignments worked great they have the same count and are the same.
However if I do the following. Run the exact same call but only break on the third line directly then this happnes
set.QuestionSet.Questions should have count of 8 BEFORE the assigment, so it seems it's not properly assigned for some reason. I suspect this has something to do with how I fetch my data from DB.
Question and QuestionSet are normal POCOs and here is the code for the entire method.
public IEnumerable<QuestionSet> SearchAndFilterQuestionsAndSets(string searchString, int nrPerPage, int page, out int totalSearchCount)
{
searchString = searchString.ToLower();
List<QuestionSet> finalList = new List<QuestionSet>();
var result = ActiveContext.QuestionSets
.Select(x => new
{
QuestionSet = x,
Questions = x.Questions.Where(
y =>
y.Description.ToLower().Contains(searchString)
).OrderBy(
z => z.Description
)
})
.ToList();
foreach (var set in result)
{
//If our search matched the set itself we load all questions
if (set.QuestionSet.Name.ToLower().Contains(searchString))
{
//we dont bring empty sets
if (set.QuestionSet.Questions.Count() > 0)
{
set.QuestionSet.Questions = set.QuestionSet.Questions.ToList<Question>().OrderBy(x => x.Description).ToList<Question>();
finalList.Add(set.QuestionSet);
}
}
//We had one or more questions matching the search term
else if (set.Questions.Count() > 0)
{
var b = set.Questions.ToList<Question>();
set.QuestionSet.Questions = set.Questions.ToList<Question>();
finalList.Add(set.QuestionSet);
}
}
totalSearchCount = finalList.Count();
return finalList.Skip((page - 1) * nrPerPage).Take(nrPerPage);
}
UPDATE
If I do this instead in the failing else if
var a = new QuestionSet();
a.Id = set.QuestionSet.Id;
a.Name = set.QuestionSet.Name;
a.Questions = set.Questions.ToList<Question>();
finalList.Add(a);
Then it works, so the problem lies within the anonymous object, but why does it work when i step through with debugger and not otherwise?? call me puzzled.
Could be something to do with Late binding of anonymous types

Entity Framework - ElementAt

I have a Table User(ID, Name....), Projects(ID, Name, Timestamps, IsFavorite...), Projects_Favoite(UserID, ProjectID)
I try to check for each projekt if there is a row for the current user. If there is a row I want set the "IsFavorite" in my Project true, otherwise false.
I tied:
for(int i = 0; i <= erg.Count();i++)
{
if (erg.ElementAt(i).User11.Any(u => u.Guid == ID) == true)
erg.ElementAt(i).SetFavorite = true;
}
but there is no way to use ElementAt, because it can't translated to SQL.
So I tried:
for(int i = 0; i <= erg.Count();i++)
{
if (erg.Take(i).Last().User11.Any(u => u.Guid == ID) == true)
erg.Take(i).Last().SetFavorite = true;
}
same problem here, so I tried:
foreach (Project project in erg)
{
if (project.User11.Any(u => u.Guid == ID))
project.SetFavorite = true;
}
There is the same problem. Is there a way to realise a ElementAt?
You should be able to do:
foreach (Project project in erg.Where(p => p.User11.Any(u => u.Guid == ID))
.ToList())
project.SetFavorite = true;
}
Assuming that erg is an IQuerable than you cannot use ElementAt as it is not supported (http://msdn.microsoft.com/en-us/library/bb399342.aspx check the section Operators With no translation), you can use it on a list though, but of course you will lose the benefits of the deferred query.
Try to use Skip instead
var whatyouwant = erg.Skip(index).First();
By looking at the stacktrace (can't read german though) looks there's something wrong with the SetFavorite column. Try first to remove this bit first:
project.SetFavorite = true;
then check also that your model columns match with what you got on the db.

is there any way to use .indexOf to search a javascript array in mirth?

I am trying to find a string in a javascript array in the transformer of a mirth channel. Mirth throws an error when I try to use indexOf function. My understanding is that indexOf is something that browsers add in, rather than a native part of the javascript language itself. ( How do I check if an array includes an object in JavaScript? )
So is array.indexOf just not supported in Mirth? Is there any way to use .indexOf in Mirth? Maybe an alternate syntax? Or do I need to just loop thru the array to search?
This is how I search arrays in a Mirth js transformer:
var Yak = [];
Yak.push('test');
if(Yak.indexOf('test') != -1)
{
// do something
}
Does this give you error?
Mirth uses the Rhino engine for Javascript, and on some earlier versions of the JVM, indexOf appeared to not be supported on arrays. Since upgrading our JVM to 1.6.23 (or higher), indexOf has started working. However, we still have legacy code that, when searching arrays of strings, I just use a loop each time:
var compareString = "blah";
var index = -1;
for (var i = 0; i < myArray.length; ++i)
{
if (myArray[i] == compareString)
{
index = i;
break;
}
}
If you need to do this frequently, you should be able to use a code template to manually add the indexOf function to Array.
Set the code template to global access, and try out something like this (untested code):
Array.prototype.indexOf = function(var compareObject)
{
for (var i = 0; i < myArray.length; ++i)
{
// I don't think this is actually the right way to compare
if (myArray[i] == compareObject)
{
return i;
}
}
return -1;
}
var arr = ['john',1,'Peter'];
if(arr.indexOf('john') > -1)
{
//match. what to do?
console.log("found");
}
else
{
console.log("not found");//not found .. do something
}
var i = ['a', 'b', 'c']
if(i.indexOf('a') > -1)
{
///do this, if it finds something in the array that matches what inside the indexOf()
}
else
{
//do something else if it theres no match in array
}

Entity Framework + conditionally appended Where() clauses

This is driving me nuts. What am I missing here. I'm using EF and if I have code like the following:
using (LexiconEntities ctx = new LexiconEntities())
{
var query = from w in ctx.Words
select new WordEntryDataModel
{
Word = w.Anagram,
NumOfAnagrams = w.NumAnagrams.Value,
Length = w.Length.Value,
...
};
SearchCriterion c1 = new SearchCriterion();
SearchCriterion c2 = new SearchCriterion();
c1.MinValue = 3;
c1.MaxValue = 3;
c2.MinValue = 4;
c2.MaxValue = 4;
query = query.Where(w => w.Length >= c1.MinValue && w.Length <= c1.MaxValue);
query = query.Where(w => w.NumOfAnagrams >= c2.MinValue && w.NumOfAnagrams <= c2.MaxValue);
...
}
And when I debug the query, I get the proper results (8 records). This also works as expected in Linqpad (which frickin' rocks).
But if I construct the search criteria as a List of criterion objects, and I dynamically add on Where() clauses by iterating over the search criteria as follows:
foreach (SearchCriterion c in criteria.SearchCriteria)
{
switch (c.Type)
{
case SearchCriterionType.WordLength:
query = query.Where(w => w.Length >= c.MinValue && w.Length <= c.MaxValue);
break;
case SearchCriterionType.NumberOfAnagrams:
query = query.Where(w => w.NumOfAnagrams >= c.MinValue && w.NumOfAnagrams <= c.MaxValue);
break;
...
case SearchCriterionType.NumberOfVowels:
query = query.Where(w => w.NumOfVowels >= c.MinValue && w.NumOfVowels <= c.MaxValue);
break;
}
}
...
I get the totally different (and incorrect) results. I've debugged the switch statement and my search criteria has two properly constructed criterion objects set to correct values. There's something about the conditionally added where clauses that my query doesn't like.
What am I doing wrong?
Closure. Assign c to a local variable within the loop. Also see my SO answer here