Spurred on by this question, I decided to try this in my MVC3/ActiveRecord application.
I have a bunch of models already working, and some views that do stuff with those models. Nothing special here. One of my models is called AppSession.
Based on said question, I expected this to work: AppSession.FirstOrDefault(a => ...) ?? null.
It didn't work. I still get an InvalidOperationException. This is true of FirstOrDefault and SingleOrDefault. I ended up wrapping my call in try/catch to get around it.
What am I doing wrong here?
Edit: As requested, the actual code is:
void getAnAppSession() {
AppSession sessions = project.AppSessions.FirstOrDefault(a => a.Ip == ip && a.MacAddress == macAddress && a.Platform == platform && a.Version == version && a.EndTime == null)
}
ip, macAddress, platform, and version are all method variables that are verifiably not null. My schema for AppSessions (and accordingly, properties on my class) includes:
ID (int, not null)
StartDate (DateTime, not null)
EndDate (DateTime, null)
Ip (string, not null)
MacAddress (string, not null)
Platform (string, not null)
Version (string, not null)
Maybe your project.AppSessions itself is null? That would cause the FirstOrDefault() method to throw an error. You might want to check if that is null before calling FirstOrDefault and create a new AppSession object if it is null:
AppSession sessions = (project.AppSessions as AppSession ?? new AppSession())
.FirstOrDefault(a => a.Ip == ip &&
a.MacAddress == macAddress &&
a.Platform == platform &&
a.Version == version &&
a.EndTime == null);
Related
Working with LINQ for the first time in a while and trying to clean something up. I have the following statements:
var element = await _Entities.References
.Where(db => db.LoadId == request.LoadId && db.ReferenceCode == "123")
.OrderByDescending(rec => rec.Created).FirstOrDefaultAsync(cancellationToken);
if (element != null) {
dto.ElementValue = element.Value;
}
I'd like to condense this into a single statement if possible but I was having trouble getting just the value from the await method.
You could do something like this:
dto.ElementValue = (await _Entity.References
.Where(db => db.LoadId == request.LoadId && db.ReferenceCode == "123")
.OrderByDescending(rec => rec.Created)
.FirstOrDefaultAsync(cancellationToken))?.Value
?? dto.ElementValue;
Note that technically this changes the behaviour of the code. Previously, if the query doesn't return a result, the ElementValue property is not touched. With a one-liner, if the query doesn't return a result, the ElementValue getter and setter will both be called.
Also, if the query returns a result whose Value is null, the ElementValue property will be set to itself rather than null.
I am consuming wcf service into angular js application. I wrote linq query to check user information . If the is not null then query should catch the information and return true otherwise its should return false . But the problem is its always returns false and catch values null
Here is the linq Query .
public bool CreateCurrentAccountCheck(Current_Account_Holder_Details current_Account_Details)
{
using (HalifaxDatabaseEntities context =new HalifaxDatabaseEntities())
{
var query = (from x in context.Current_Account_Holder_Details
where x.Account_Holder_First_Name == current_Account_Details.Account_Holder_First_Name && x.Account_Holder_Last_Name == current_Account_Details.Account_Holder_Last_Name
&& x.Account_Holder_DOB == current_Account_Details.Account_Holder_DOB && x.Account_Holder_House_No == current_Account_Details.Account_Holder_House_No
&& x.Account_Holder_Street_Name == current_Account_Details.Account_Holder_Street_Name && x.Account_Holder_Post_Code == current_Account_Details.Account_Holder_Post_Code
select x).FirstOrDefault();
if (query!=null)
{
return true;
}
else
{
return false;
}
}
}
Here is the screen shot on debugging Mode .
The problem is pretty clear that there is no matched record with the where clauses. Also, you want to check the record and you should check it with using an unique id instead of other required or not required fields. It is the exact way to apply it. You should have some kind of unique AccountDetailId or other name which applies unique info for the records.
var query = (from x in context.Current_Account_Holder_Details
where x.AccountDetailId == current_Account_Details.AccountDetailId
select x).FirstOrDefault();
The HTML Source is as follows
<img id="itemImage" src="https://www.xyz.com/item1.jpg">
I am using the following LINQ query to get the SRC value (Image Link)
string imageURL = document.DocumentNode.Descendants("img")
.Where(node => node.Attributes["id"] != null && node.Attributes["id"].Value == "itemImage")
.Select(node => node.Attributes["src"].Value).ToString();
But the imageURL gives output as
System.Linq.Enumerable+WhereSelectEnumerableIterator`2[HtmlAgilityPack.HtmlNode,System.String]
The problem is casting it to string. Select() returns IEnumerable<T> so you are basically converting an enumerator to a string (as the error message says). Call First() or Single() or Take(1) in order to get a single element before casting it to a string.
.Select(node => node.Attributes["src"].Value).First().ToString();
Also, if there is a chance that the desired element is not present, FirstOrDefault() and SingleOrDefault() returns null rather then throwing an exception. In that case, I would recommend
var imageUlr = ... .Select(node => node.Attributes["src"].Value).FirstOrDefault();
if (imageUrl != null)
{
// cast it to string and do something with it
}
Add .DefaultIfEmpty(string.Empty)
.FirstOrDefault
string imageURL = document.DocumentNode.Descendants("img")
.Where(node => node.Attributes["id"] != null && node.Attributes["id"].Value == "itemImage")
.Select(node => node.Attributes["src"].Value)
.DefaultIfEmpty(string.Empty)
.FirstOrDefault()
.ToString();
Try adding FirstOrDefault():
string imageURL = document.DocumentNode.Descendants("img")
.Where(node => node.Attributes["id"] != null && node.Attributes["id"].Value == "itemImage")
.Select(node => node.Attributes["src"].Value)
.FirstOrDefault();
for unit-testing my asp.net MVC web application, I'd like to mock my IGenericRepository (I'm using Moq).
The method that has to be mocked looks like this:
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
I've already mocked the repository without any problems:
useraccountRepository = new Mock<IGenericRepository<Useraccount>>();
Now I'd like to tell Moq that when the Get method of my interface is called, a list of useraccounts should be returned:
useraccountRepository.Setup(r => r.Get(u => u.Email == useraccount.Email && u.Password == useraccount.Password)).Returns(useraccounts);
I think there is a mistake in my second lambda because this one works:
useraccountRepository.Setup(r => r.Get(null, null, "")).Returns(useraccounts);
But where's my error?
What also works:
useraccountRepository.Setup(r => r.Get(u => u.Email == useraccount.Email
&& u.Password == useraccount.Password, null, "")).Returns(useraccounts);
It looks like the default parameter values don't apply in my mock. Why is that?
If I use
useraccountRepository.Setup(r => r.Get(u => u.Email == useraccount.Email
&& u.Password == useraccount.Password, null, "")).Returns(useraccounts);
anyway, then the method in my controller throws an exception when the Get message is called:
private bool validateUser(Useraccount useraccount)
{
try
{
Useraccount useraccountLogin = UnitOfWork.UseraccountRepository.Get(
u => u.Email == useraccount.Email && u.Password == useraccount.Password).Single<Useraccount>();
return (useraccountLogin != null);
}
catch (Exception exc)
{
return false;
}
}
Where are my mistakes?
Thank you in advance.
Michael
According to this question Moq.Mock<T> - how to setup a method that takes an expression, setting constraints on expression parameters is unsupported by Moq.
Why doesn't my linq query work?
I suspect it may have something to do with lazy loading. It seems to work in linqpad.
public IList<PaymentDto> GetDocumentPayments(int documentId, bool? allowRepeatPayments, byte[] paymentStatuses, int[] paymentMethods)
{
using (var ctx = ObjectContextManager<MyDataContext>.GetManager("MyDataContext"))
{
var payments = new List<PaymentDto>();
var ps = new List<byte>();
if (paymentStatuses != null)
{
ps = paymentStatuses.ToList();
}
var pm = new List<int>();
if (paymentMethods != null)
{
pm = paymentMethods.ToList();
}
IQueryable<Payment> data =
from payment in ctx.ObjectContext.Documents.OfType<Payment>()
where
ps.Contains(payment.Status) &&
pm.Contains(payment.Method) &&
payment.DocumentId == documentId &&
(allowRepeatPayments == null || payment.AllowRepeatPayments == allowRepeatPayments)
orderby payment.Id
select payment;
foreach (var p in data) // Fails here
{
payments.Add(ReadData(p));
}
return payments;
}
}
Throws error: A CollectionType is required.
Parameter name: collectionType.
Constructs like (allowRepeatPayments == null || payment.AllowRepeatPayments == allowRepeatPayments) can do funny thing to a query. Try what happens when you do:
if (allowRepeatPayments.HasValue)
{
data = data.Where(p => p.AllowRepeatPayments == allowRepeatPayments);
}
You can do the same for paymentStatuses and paymentMethods.
It may solve your problem, but if not, it is an improvement anyway, because the condition is only added when it is necessary and the SQL is not cluttered when it isn't.
The exception is thrown by internal methods of the framework while translating LINQ query to SQL, with the same kind of constructs for null checks as the one you are using (for example
.Where(data => x & y & (values == null || values.Contains(data.value)));)
I just experienced the same exception on a server running the earliest version of .Net 4 RTM (4.0.30319.1).
It comes from
exception : System.ArgumentException: A CollectionType is required.
Parameter name: collectionType
at System.Data.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.ValidateNewEmptyCollection(TypeUsage collectionType, DbExpressionList& validElements)
at System.Data.Objects.ELinq.ExpressionConverter.NewArrayInitTranslator.TypedTranslate(ExpressionConverter parent, NewArrayExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) ...
The error is very rare on the internet, and it doesn't happen with same conditions and newer versions, so it seems to have been fixed on more recent versions of .Net.
The suggestion of Gert Arnold will probably also allow to avoid the error, but the form above is oftenly used (like is SQL counterpart) and it's short and useful.
So for those who still encounter this error and don't understand why it works on some machine and sometimes not, I suggest to check their .Net FW version.