ObjetosAuxiliar.ReservaServicoResumo resumoServico = new ObjetosAuxiliar.ReservaServicoResumo();
resumoServico.Quantidade = this.ReservaServico.Sum(r => r.Quantidade);
resumoServico.ValorTotal = this.ReservaServico.Sum(r => r.Quantidade * r.Servico.Valor);
resumoServico.Servico = r.Servico; --WRONG
return resumoServico;
How to get in resumoServico.Servico the object r.Servico?
I think you are misunderstanding something.
r is not a real object (per se), is a representation that you use for the ReservaServico in order to use the Sum method, r only exists inside the call for that method.
So, I think what you are looking for is:
resumoServico.Servico = this.ReservaServico.Servico;
UPDATE
If ReservaServico is a collection, the only way of get the values is to store them in a collection, if this is the case you can do it this way.
ObjetosAuxiliar.ReservaServicoResumo resumoServico = new ObjetosAuxiliar.ReservaServicoResumo();
resumoServico.Quantidade = this.ReservaServico.Sum(r => r.Quantidade);
resumoServico.ValorTotal = this.ReservaServico.Sum(r => r.Quantidade * r.Servico.Valor);
foreach(var r in ReservaServico)
{
resumo.Servico.Add(r.Servico);
}
For this to work, resumo.Servico has to be a collection of ReservaServico.Servico, if you can't change the type you can't have the collection of Servico.
Related
As the question suggests I want to remove the columns from a select query where in that column are empty.
var query = from a in ...
select new
{
A =(decimal?)null,
B =(decimal?)null,
C = a.Amount1
};
var query2 = from b in ...
select new
{
A = b.Amount2,
B = b.Amount3,
C = (decimal?)null
};
var query3 = query.Concat(query2);
Output:
query3=[0]{A=null, B=null, C=100.00}
[1]{A=100.00, B=50.25, C=null}
Expected Result:
query3=[0]{C=100.00}
[1]{A=100.00, B=50.25}
You can't do this. The result set has to contain items of the same type and even if fields are null they still have to be there.
You could not show them in your UI, but exactly how you do that will depend on the UI.
You can't. A class has a predefined set of fields (not to speak about ExpandoObject which has some compiler tricks going on). This is the same for anonymous type, which you use.
You can't just hide or remove fields which are not filled. What if you iterate over the instances and try to retrieve item.C, which was null and thus removed? That would normally give you a compiler error. How would .NET resolve that?
The only other thing you can do is put in two different types in your list (a list of objects, so untyped), a very bad idea in my opinion. Keep it like this. You could add an indicator which type the row is, to be able to test it easily.
So:
select new
{
Type = "A", // or "B"
A =(decimal?)null,
B =(decimal?)null,
C = a.Amount1
};
A LINQ query typically outputs objects of a common type, so each object has to have the same base type (and the columns associated. The only way to concatenate objects of different types is to cast them to object:
var query = from a in ...
select new
{
C = a.Amount1
};
var query2 = from b in ...
select new
{
A = b.Amount2,
B = b.Amount3,
};
var query3 = query.Cast<object>().Concat(query2.Cast<object>());
but since they're anonymous you'll have to use dynamic to access them since you won;t be able to cast back to the original type, so you'll end up with something like this:
Console.WriteLine(((dynamic)(query3[0])).C);
Console.WriteLine(((dynamic)(query3[1])).A);
or at best:
dynamic list = query3.ToList();
Console.WriteLine(list[0].C);
Console.WriteLine(list[1].A);
but in any case you'll lose compile-time type safety.
I get an item from the list to manuplate it.
App.CurrentQuestion = App.AllQuestionList[dataSourceRowIndex];
After manuplations I save new data to database and get back from database into App.CurrentQuestion, so App.CurrentQuestion's list reference breaks. I want to update list and trying to focus selected item by linq
App.AllQuestionList
.Where(q => q.qID == App.CurrentQuestion.qID)
.FirstOrDefault() = App.CurrentQuestion;
but I get an error like "The left-hand side of an assignment must be a variable, property or indexer"
I can use this method
for (int i = 0; i < App.AllQuestionList.Count; i++)
{
if (App.AllQuestionList[i].qID == App.CurrentQuestion.qID)
{
App.AllQuestionList[i] = App.CurrentQuestion;
break;
}
}
but looking for an alternative method. Or is there any faster method?
You shouldn't have to do anything, since it's by reference.
App.CurrentQuestion = App.AllQuestionList[dataSourceRowIndex];
Whatever change you make in App.CurrentQuestion should be reflected in the App.AllQuestionList
App.AllQuestionList[App.AllQuestionList.IndexOf(App.AllQuestionList.
.Where(q => q.qID == App.CurrentQuestion.qID)
.First())] = App.CurrentQuestion;
Edit: you can just use the IndexOf to find the index of the object you wanted to find by LINQ query
I'm trying to have a one-liner LINQ statement to project my one object to my ViewModel object - it seems it won't work with select?? The compiler says cannot resolve symbol select. This works with a collection, why doesn't it here? If not select, what keyword am I missing?
return from p in SettingRepository.Get(id)
select new EditSetting
{
};
Edit - Scratch that, doesn't work for a list. How can I accomplish this?
Although I'm not sure why you would want to use select to do this, but if you're really adamant about it:
return from p in new List<EntityObject>{SettingRepository.Get(id)}
select new EditSetting
{
};
If not, why not just use good old initializers?
var editSetting= new EditSetting { Id = setting.Id };
Typically I prefer to create methods with the following pattern. It discourages tight looping of Database calls, which can severely limit performance. Still Bryan Hong's answer is the actual ANSWER to your question.
public IQueryable<EditSetting> GetEditSettings()
{
return from p in SettingRepository
select new EditSetting{
Foo = p.Foo,
Bar = p.Bar,
//etc...
};
}
or
public IEnumerable<EditSetting> GetEditSettingsById(IList<string> ids)
{
var ret = from p in SettingRepository
where ids.Contains(p.Id)
select new EditSetting{
Foo = p.Foo,
Bar = p.Bar,
//etc...
};
return ret.ToList();
}
This method:
private async Task readFileInfo(string folderId)
Has a call to another method:
importCount = await VM.importVehicles(myXDoc);
Defined here: (note: I changed it from a for loop to a for each but I'm getting similar results).
public async Task<Int32> importVehicles(XDocument importXMLDocument)
{
var Importedvehicles = from vehicle in importXMLDocument.Descendants("vehicle")
select new
{
VehicleName = vehicle.Element("VehicleName").Value,
VehicleYear = vehicle.Element("VehicleYear").Value,
Odometer = vehicle.Element("Odometer").Value,
LicensePlate = vehicle.Element("LicensePlate").Value,
OilWeight = vehicle.Element("OilWeight").Value,
OilQuantity = vehicle.Element("OilQuantity").Value,
OilFilterModelNumber = vehicle.Element("OilFilterModelNumber"),
AirFilterModelNumber = vehicle.Element("AirFilterModelNumber"),
OilChangedDate = vehicle.Element("OilChangedDate"),
OilChangedOdometer = vehicle.Element("OilChangedOdometer"),
NextOilChangeDate = vehicle.Element("NextOilChangeDate"),
NextOilChangeOdometer = vehicle.Element("NextOilChangeOdometer"),
SettingDistance = vehicle.Element("SettingDistance"),
SettingMonths = vehicle.Element("SettingMonths"),
};
Int32 vehicleId;
vehicleId = await getMaxVehicleId();
try
{
foreach (var item in Importedvehicles)
{
vehicle myImportedVehicle = new vehicle();
myImportedVehicle.VehicleId = vehicleId += 1;
myImportedVehicle.ImagePath = "Assets/car2.png";
myImportedVehicle.VehicleName = item.VehicleName;
myImportedVehicle.VehicleModel = item.VehicleName;
myImportedVehicle.VehicleYear = short.Parse(item.VehicleYear);
myImportedVehicle.CurrentOdometer = Convert.ToInt32(item.Odometer);
myImportedVehicle.LicensePlate = item.LicensePlate;
myImportedVehicle.LastOilChangedDate = Convert.ToDateTime(item.OilChangedDate.Value.ToString()).ToString("d");
myImportedVehicle.LastOilChangedOdometer = (Int32)item.OilChangedOdometer;
myImportedVehicle.ReminderDistance = (Int32)item.SettingDistance;
myImportedVehicle.ReminderMonths = (Int32)item.SettingMonths;
vehicleInformation myImportVI = new vehicleInformation();
myImportVI.OilWeight = item.OilWeight;
myImportVI.OilAmount = item.OilQuantity;
myImportVI.OilFilterNumber = item.OilFilterModelNumber.Value.ToString();
myImportVI.AirFilterNumber = item.AirFilterModelNumber.Value.ToString();
myImportedVehicle.vehicleInfo = myImportVI;
m_vehicles.Add(myImportedVehicle);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message.ToString());
}
await SaveList();
return Importedvehicles.Count();
}
I'm getting an error:
Object reference not set to an instance of an object.
when I step through it the iVehicle is highlighted but then it goes directly to the for statement. Then it errors as it looks as it hasn't gotten the results from iVehicle yet.
This doesn't 100% answer your question, but it should give you a good start.
The reason the debugger jumps straight into the for...loop after the declaration of iVehicle, is because your query does not get executed when you declare it. Therefore, iVehicle at that point is not a collection of anonymous types.
When you call .Count(), the query is being executed and iVehicle is attempting to be turned into a proper collection of anonymous types. However, because something in the query (that is being executed after you call .Count()) is null, you're receiving an NullReferenceException.
You should start by verifying that both importXMLDocument and the return value from the call to Descendants() is not null.
Hope that helps anyway.
EDIT:
Now that you've given a complete example, you have heaps of places that could potentially be null.
Each time you use this:
vehicle.Element("SomeElementNameHere")
That could potentially be null. Then you're calling the .Value property on a null object.
You need to make sure each element is definitely there. Isolate each case, and determine which one is null.
Try writing your code like this:
var query =
from vehicle in importXMLDocument.Descendants("vehicle")
select new { ... };
var iVehicle = query.ToArray();
for (var i = 0; i <= iVehicle.Count(); i++)
{
...
}
You need to force the evaluation of the query. That's what the .ToArray is doing. The query itself is only the definition of the query, not the results.
Is there a way to add a property to the objects of a Linq query result other than the following?
var query = from x in db.Courses
select new
{
x.OldProperty1,
x.OldProperty2,
x.OldProperty3,
NewProperty = true
};
I want to do this without listing out all of the current properties of my object. There are many properties, and I don't want to have to update this code whenever I may change my class.
I am still learning with LINQ and I appreciate your suggestions.
Add it with partial classes:
public partial class Courses
{
public String NewProperty { get; set; }
}
Then you can assign it after you've created the object.
I suppose you could return a new object composed of the new property and the selected object, like this:
var query = from x in db.Courses
select new
{
Course = x,
NewProperty = true
};
eking's answer will be the most straightforward approach.
If that doesn't work for you (because you need to pass the results around or whatever), and assuming the class you're dealing with already defines the property you want to set, you could create a copy constructor or factory method that takes an existing instance plus the value of the property you want to set:
var query = from x in db.Courses
select new Course(x, valueOfNewProperty);
Alternatively, if Course doesn't define the property, you could subclass it and use the same approach:
var query = from x in db.Courses
select new CourseWithExtraProperty(x, valueOfNewProperty);
(obviously, pick a better name for your subclass)
Again, though, unless you really need to do this, stick with eking's solution.
ServiceStack has a built-in way to handle this with the PopulateWith method.
Here's a code example.
foreach (var item in results)
{
var test1 = new ItemDto().PopulateWith(item);
test1.extraField1 = "extra";
response.Add(test1);
}`
And if you're not using ServiceStack, you can always use AutoMapper.
CreateMap<Foo, Bar>().ForMember(x => x.ExtraBarProperty, opt => opt.Ignore());
If you are looking to dynamically add a property to an object this could be a solution.
This is what has worked for me, I also had a concern and it was what happened with those domain objects that had many properties, the maintainability for any changes in the object was absurd, I managed to build an implementation with LINQ - ExpandObject - Reflection, which helped to keep my object dynamic and only add the additional properties that my view logic required.
var expandedModel = db.Courses.Select(x =>
{
dynamic expandObject = new ExpandoObject();
expandObject.NewProperty= $"PropertyValue";
foreach (var property in x.GetType().GetProperties())
{
((IDictionary<string, object>)expandObject).Add(property.Name, property.GetValue(x));
}
return expandObject;
}).ToList();