What Output type this method? [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Return anonymous type from LINQ query?
I use this Method:
public static ... GetList()
{
Entity conn = new Entity();
var lst = (from PS in conn.PurchaserSpecials
select new
{
PS.PurchaserID,
PS.PurchaserSerial,
PS.Purchaser.Address,
PS.Purchaser.Fax,
PS.Purchaser.NumberEconomic
}).ToList();
return lst;
}
can not use var for output Type. Please help me...
what is output the method?

It's a list of the anonymous type you created.
If you want to return a type that you would know, create a new class that has the fields you are selecting (I am guessing types below):
public class Specials
{
public int PurchaserID { get; set; }
public int PurchaserSerial { get; set; }
public string Address { get; set; }
public int Fax { get; set; }
public int NumberEconomic { get; set; }
}
public static List<Specials> GetList()
{
Entity conn = new Entity();
var lst = (from PS in conn.PurchaserSpecials
select new Specials
{
PurchaserID = PS.PurchaserID,
PurchaserSerial = PS.PurchaserSerial,
Address = PS.Purchaser.Address,
Fax = PS.Purchaser.Fax,
NumberEconomic = PS.Purchaser.NumberEconomic
}).ToList();
return lst;
}

You LINQ query generates an anonymous type, and as such can't be used as a return type of the method, and the calling method will not know anything about the return type.
A way around this is to make use of the dynamic keyword and dynamic types.
The return type of you method can be like this
public dynamic GetList() {
return ...;

The output of the query is an anonymous type which you can not return back as a parameter. To be simple, better you create a class something like : 'PurchaseDetail' with all those properties and return the code like :
public static List<PurchaseDetail> GetList()
{
Entity conn = new Entity();
var lst = (from PS in conn.PurchaserSpecials
select new PurchaseDetail
{
PurchaserID= PS.PurchaserID,
PurchaserSerial=PS.PurchaserSerial,
Address=PS.Purchaser.Address,
Fax=PS.Purchaser.Fax,
NumberEconomic =PS.Purchaser.NumberEconomic
}).ToList();
return lst;
}

The Return Type would be the List of type Products
public static List<Products> GetList()
{
Entity conn = new Entity();
var lst = (from PS in conn.PurchaserSpecials
select new
{
PS.PurchaserID,
PS.PurchaserSerial,
PS.Purchaser.Address,
PS.Purchaser.Fax,
PS.Purchaser.NumberEconomic
}).ToList();
return lst;
}
public class Products
{
//Properties you are using in the query.
}

Related

C# Linq query not returning an Enumerable collection

I am new C# and EF and LINQ
I am trying to learning (much like a toddler) how to do this so apologies if this is obvious
I am getting a type conversion error when i create a LINQ query
namespace ABC.Pages
{
public partial class AOmMainComponent
{
[Inject]
MydbContext MydbContext { get; set; }
public IEnumerable<OMSite> OMSites()
{
var Sites = from s in MydbContext.TblOms select new {SiteId = s.OMID, SiteName = s.OMSite };
return (IEnumerable<OMSite>)Sites;
}
}
public class OMSite
{
public int SiteID { get; set; }
public string SiteName { get; set; }
}
}
I've tried:
return Sites;
and I've tried
return (IEnumerable<OMSite>)Sites;
but neither work.Please can someone advise what i'm doing wrong?
thanks
john
Change:
var Sites = from s in MydbContext.TblOms select new {SiteId = s.OMID, SiteName = s.OMSite };
To:
var Sites = from s in MydbContext.TblOms select new OMSite {SiteId = s.OMID, SiteName = s.OMSite };
Particulary select new { -> select new OMSite{. After that return Sites; should work.
Your current code creates IEnumerable of anonymous types which can not be cast to IEnumerable<OMSite> which your IEnumerable<OMSite> OMSites() method expects to be returned.
You need to create the specific object in your projection:
var Sites = from s in MydbContext.TblOms select new OMSite {SiteId = s.OMID, SiteName = s.OMSite };
Your method is expecting you return IEnumerable<OMSite> and your query is creating an IEnumerable of a Anonymous types

How to convert void to implicitly local variable?

Here I'm writing logic in class file and implementing in a controller. When I'm trying to implement the code in the controller it's throwing an error as "cannot assign void to an implicitly-typed local variable"
public void Getass()
{
var xx = from n in db.Accessors
join cn in db.Countrys on n.CountryID equals cn.CountryID
select new
{
n.Name,n.Id,n.CountryID,
cn.CountryName};
}
Dummy.cs
public JsonResult tt()
{
var sss= objrepo.Getass();
return new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Getass should return the collection but it is an anonymous type. Either create it in the method making the call
public JsonResult tt()
{
var xx = from n in db.Accessors
join cn in db.Countrys on n.CountryID equals cn.CountryID
select new
{
n.Name,
n.Id,
n.CountryID,
cn.CountryName
};
return Json(xx, JsonRequestBehavior.AllowGet);
}
or create a class to hold the result
public class MyModel {
public string Name { get; set; }
public string Id { get; set; }
public string CountryID { get; set; }
public string CountryName { get; set; }
}
public IList<MyModel> GetAccessors()
{
var xx = from n in db.Accessors
join cn in db.Countrys on n.CountryID equals cn.CountryID
select new MyModel
{
Name = n.Name,
Id = n.Id,
CountryID = n.CountryID,
CountryName = cn.CountryName
};
return xx.ToList();
}
public JsonResult tt()
{
var sss= objrepo.GetAccessors();
return Json(sss, JsonRequestBehavior.AllowGet);
}
You'll need to create a concrete type to return that from your method. void means the method doesn't return anything, and you can't use var as a return type.
So your choices are:
Create a concrete type and have your query create objects of that type (and change your return type to IEnumerable<{type}> or similar
Put the query from Getass inside the tt method so you can use an anonymous type.
you can't return a void type and expecting a result that you can assign to a variable
more you are creating an anonymous type by doing this
select new {
n.Name,n.Id,n.CountryID,
cn.CountryName};
if you want to return it oops,
you can't return an anonymous type because you haven't the name at compilation time. c# will assign an arbitrary name once compiled so you have to use object type
You can only return object, or container of objects, e.g. IEnumerable<object>, IList<object>, etc.

Return non-anonymous list entity framework - c#

I have 2 tables in the database :
Table: Order (item_id)
Table: Item ( item_id)
When I'm doing the inner join in entity framework, as you can see below, I need to return in one list the result to manipulate this. Usually when I do the select in one single table , I return a LIST from the entity with the tables name, but I dont know how can I return a LIST when I have 2 or more entity , I mean, using inner join, I would like to return a List that I can manipulate in other class. When I use for only one entity, it is perfect and easy.
public List<????????> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new
{
a.order_numer,
a.total,
b.item_code,
b.item_qty
});
return _result;
}
I don't know how to return it !! I tried to use the .TOLIST(), but still coming "anonymous".
Thank you
First you need to create a custom type like
public class OrderItems
{
public int Order_numer { get; set; }
public int Total { get; set; }
public string Item_code { get; set; }
public int Item_qty { get; set; }
}
After then modify your function like
public List<OrderItems> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new OrderItems()
{
Order_numer= a.order_numer,
Total= a.total,
Item_code=b.item_code,
Item_qty=b.item_qty
}).ToList();
return _result;
}
I hope it will work for you.
You can create a compound model that has a property representing each entity.
public class CompoundModel
{
public Entities.Order { get; set; }
public Entities.Item { get; set; }
}
public List<CompoundModel> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new CompoundModel
{
Order = a
Item = b
});
return _result;
}
Alternatively, if you want to flatten your structure, you can create a class that only has four properties.
public class CompoundModel
{
public string OrderNumber { get; set; }
public int Total { get; set; }
public string ItemCode { get; set; }
public int ItemQuantity { get; set }
}
public List<CompoundModel> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new CompoundModel
{
OrderNumber = a.order_number,
Total = a.total,
ItemCode = b.item_code,
ItemQuantity = b.item_qty
});
return _result;
}
The problem with your code is this part:
select new // This will create an anonymous type
{
a.order_numer,
a.total,
b.item_code,
b.item_qty
}
As the select generates an anonymous type you will get a list of theses anonymous types as a result of the query. In order to get a list typed results, you need to specify the type in the select-clause:
select new TypeYouWantToReturn() // This will create an real type
{
PropA = a.order_numer, // You also need to specify the properties
PropB = a.total, // of the class that you want to assign
PropC = b.item_code, // the resulting values of the query.
PropD = b.item_qty
}
Now the result of the query will return a list of real types. You need to finally call .ToList() so you get a list instead of the IEnumerable that the select statement will return.

Dynamically set the table name in LINQ query

I am working on data warehouse application and we have 4 tables where schema is identical. Only difference between those tables is just Table Name.
Table Example:
ps_Contractor
ps_Employee
ps_Union
ps_NonUnion
Schema
id
hourly
benefit
total
Now i need to generate 4 reports based on these tables. Instead of writing 4 separate LINQ queries i would like to write single query where i can pass the table name dynamically.
The question How do i pass the table name dynamically in following LINQ query ?
var data = ( from q in _dbcontext.ps_Contractor
join _l in _dbcontext.log on q.id equals l.tablelogid
where q.hourly = 8
select new{
hourly=q.hourly,
benefit=q.benefit,
total=q.total,
log = l.message
}.ToList();
I have looked at all similar questions suggested by stack overflow. I do not want to use ExecuteStoreQuery.
what options do i have ?
If all the tables have the same columns, then I'd extract an interface out of those tables and create partial entity classes just to implement that interface, finally use that interface to query.
For example:
//entities
public partial class ps_Contractor: ICommonInterface{}
public partial class Table2 : ICommonInterface{}
in the search method I'd pass IEnumerable<ICommonInterface> or IQueryable<ICommonInterface> and apply that query on that. All you'd need to do is to pass different tables to that search method.
Or you can even have kind of generic class of type ICommonInterface and use that to do the query.
public void Example(IQueryable<ICommonInterface>dataSource)
{
var data = ( from q in dataSource
join _l in _dbcontext.log on q.id equals l.tablelogid
where q.hourly = 8
select new{
hourly=q.hourly,
benefit=q.benefit,
total=q.total,
log = l.message
}.ToList();
}
Example(_dbcontext.ps_Contractor.AsQueryable())
This is just a sample that I tested now:
public class Repository
{
private List<string> GetData(IQueryable<IContractor> data)
{
return (from d in data select d.Name).ToList();
}
public List<string> GetFullTime()
{
using (var context = new TestDbEntities())
{
return GetData(context.FTContractors.AsQueryable());
}
}
public List<string> GetPartTime()
{
using (var context = new TestDbEntities())
{
return GetData(context.PTContractors.AsQueryable());
}
}
}
Entities:
public interface IContractor
{
int Id { get; set; }
string Name { get; set; }
}
public partial class FTContractor : IContractor
{
public int Id { get; set; }
public string Name { get; set; }
}
public partial class PTContractor : IContractor
{
public int Id { get; set; }
public string Name { get; set; }
}
Test:
[TestMethod]
public void Temp()
{
var tester = new Repository();
var ft = tester.GetFullTime();
var pt = tester.GetPartTime();
Assert.AreEqual(3, ft.Count);
Assert.AreEqual(4, pt.Count);
}
In the database there are two tables containing just Id and Name columns
EF Core no longer has a non generic .set method but This extension class makes it easy to query your table based on a string using dynamic Linq
public static class DbContextExtensions
{
public static IQueryable<Object> Set(this DbContext _context, Type t)
{
return (IQueryable<Object>)_context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
}
public static IQueryable<Object> Set(this DbContext _context, String table)
{
Type TableType = _context.GetType().Assembly.GetExportedTypes().FirstOrDefault(t => t.Name == table);
IQueryable<Object> ObjectContext = _context.Set(TableTypeDictionary[table]);
return ObjectContext;
}
}
}
usage:
IQueryable<Object> query = db.Set("TableName");
// Filter against "query" variable below...
List<Object> result = query.ToList();
// or use further dynamic Linq
IQueryable<Object> query = db.Set("TableName").Where("t => t.TableFilter == \"MyFilter\"");
Here's a way to do a dynamic function that accepts a DbSet<T> (type of database class that you want to pass as a parameter) and a specific expression to build a query on that table:
private IQueryable<T> BuildQueriedCollection<T>(Expression<Func<T, bool>> exp, DbSet<T> dbTable) where T : class
{
var appliedQueryCollection = dbTable.AsExpandable().Where(exp);
return appliedQueryCollection;
}
and you could call the function like so:
Expression<Func<MyClass, bool>> myExp = myList => myList... // some condition...;
var dbset = dbContext.MyTable;
var query = BuildQueriedCollection(myExp, dbset);

How to select all the values of an object's property on a list of typed objects in .Net with C#

Ugh, how do I explain this one... Probably a simple question but my mind is fried.
Suppose I have this class:
public class NestedObject
{
public string NestedName { get; set; }
public int NestedIntValue { get; set; }
public decimal NestedDecimalValue { get; set; }
}
public class SomeBigExternalDTO
{
public int Id { get; set; }
public int UserId { get; set; }
public int SomeIntValue { get; set; }
public long SomeLongValue { get; set; }
public decimal SomeDecimalValue { get; set; }
public string SomeStringValue { get; set; }
public NestedObject SomeNestedObject { get; set; }
// ... thousands more of these properties... inherited code
}
And the class I'd like to populate is here:
public class MyResult
{
public int UserId { get; set; } // user id from above object
public string ResultValue { get; set; } // one of the value fields from above with .ToString() executed on it
}
What I'd like to do is create a helper to return the property values (a cross section is the best way I could describe it I guess) of all instances in a list of this object:
var foo = new List<SomeBigExternalDTO>();
foo = GetMyListOfSomeBigExternalDTO();
public static List<MyResult> AwesomeHelper(List<SomeBigExternalDTO> input, SearchableProperty thePropertyIWant)
{
// some magic needs to happen here...
}
The tricky part here is I want to dynamically pass in the property based on a link selector (I have no clue how to do this):
var output = AwesomeHelper(GetMyListOfSomeBigExternalDTO(), x => x.SomeIntValue);
var output2 = AwesomeHelper(GetMyListOfSomeBigExternalDTO(), x => x.SomeNestedObject.NestedIntValue);
And this should return a list of MyResult objects with the UserId and SomeIntValue.ToString() corresponding to each item in the input list.
Wow, I really hope this makes sense. Please let me know if this is not clear I'll provide more details. I'm really hoping this is something baked into the libraries that I've overlooked.
Any ideas on I'd accomplish this?
You could implement it as an extension method:
public static IEnumerable<MyResult> AwesomeHelper(this IEnumerable<SomeBigExternalDTO> input,
Func<SomeBigExternalDTO, int> intMapper)
{
foreach (var item in input)
yield return new MyResult()
{
UserId = item.UserId,
ResultValue = intMapper(item)
};
}
Now you can use it like this:
var output = GetMyListOfSomeBigExternalDTO().AwesomeHelper( x => x.SomeIntValue);
var output2 = GetMyListOfSomeBigExternalDTO().AwesomeHelper( x => x.SomeNestedObject.NestedIntValue);
Having said that - dont' do that - it somehow looks like you are reinventing what Linq already offers you, you can do just the same using only Linq:
var output = GetMyListOfSomeBigExternalDTO().Select( x=> new MyResult()
{
UserId = item.UserId,
ResultValue = x.SomeIntValue
});
var output2 = GetMyListOfSomeBigExternalDTO().Select( x=> new MyResult()
{
UserId = item.UserId,
ResultValue = x.SomeNestedObject.NestedIntValue
});
Often when trying to create a general purpose list operator you end up reimplementing what LINQ already offers you.
Here's the LINQ code for what you're after (without an AwesomeHelper function):
var results = list.Select(l => new MyResult()
{
UserId = l.UserId,
ResultValue = l.SomeDecimalValue.ToString()
}).ToList();
Fairly simple.
If you want to have an AwesomeHelper function as you requested then it looks like this:
public static List<MyResult> AwesomeHelper(
List<SomeBigExternalDTO> input,
Func<SomeBigExternalDTO, object> selector)
{
return input
.Select(i => new MyResult()
{
UserId = i.UserId,
ResultValue = selector(i).ToString()
})
.ToList();
}
And the calling code look like this:
var results = AwesomeHelper(list, x => x.SomeIntValue);
To me, though, this is now less readable than the LINQ option. Now there is some magic being wrought and it's hard to work out what.
I have an alternative that will give you the best of both worlds.
First, define an extension method called ToMyResult that maps a single SomeBigExternalDTO instance into a single MyResult with a field selector, like this:
public static class AwesomeHelperEx
{
public static MyResult ToMyResult(
this SomeBigExternalDTO input,
Func<SomeBigExternalDTO, object> selector)
{
return new MyResult()
{
UserId = input.UserId,
ResultValue = selector(input).ToString()
};
}
}
Now the calling code is crystal clear, flexible and concise. Here it is:
var results = (
from item in list
select item.ToMyResult(x => x.SomeLongValue)
).ToList();
I hope this helps.

Categories