Column referenced is not in scope: '' - c#

Hallo I'm still newbie in linq and programming
I'm trying to make a report using crystal report with linq query and to put it into datatable I'm using function that throw, but got Column referenced is not in scope: ''..
I'm trying to joining 3 tables.
this is a function that I've found from internet
public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
DataTable dtReturn = new DataTable();
// column names
PropertyInfo[] oProps = null;
if (varlist == null) return dtReturn;
foreach (T rec in varlist)
{
// Use reflection to get property names, to create table, Only first time, others will follow
if (oProps == null)
{
oProps = ((Type)rec.GetType()).GetProperties();
foreach (PropertyInfo pi in oProps)
{
Type colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()
== typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
}
DataRow dr = dtReturn.NewRow();
foreach (PropertyInfo pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
and here is my linq
var id = (from u in myDb.TBL_TRANSAKSI_MKN_MNMs
join l in myDb.TBL_DETAIL_TRANSAKSIs on u.ID_NOTA equals l.ID_NOTA
//into g1
join m in myDb.TBL_MKN_MNMs on l.ID_MKN_MNM equals m.ID_MKN_MNM
//into g
group new {u,l,m} by new {u.TGL_TRANSAKSI, m.NAMA_MKN_MNM, m.HARGA_JUAL, l.ID_MKN_MNM, u.USERNAME}
into grp
where grp.Key.TGL_TRANSAKSI.Value.Date.Equals(dateTimePicker1.Value.Date)
select new
{
MakanMinum = grp.Key.NAMA_MKN_MNM,
HargaJual = grp.Key.HARGA_JUAL,
sumStok = grp.Sum(groupedthing => groupedthing.l.ID_MKN_MNM),
Tanggal = grp.Key.TGL_TRANSAKSI,
Jumlah = grp.Key.HARGA_JUAL * grp.Sum(groupedthing => groupedthing.l.ID_MKN_MNM),
Total = grp.Sum(grouptotal => grp.Key.HARGA_JUAL * grp.Sum(groupedthing => groupedthing.l.ID_MKN_MNM)),
Username = grp.Key.USERNAME
});
I've got a throw in line foreach (T rec in varlist)
is there any simple query..?? because I'm confuse to join 3 tables...
thank you for the advance

I think your problems is:
your query result is anonymous type ,so you should change your code like this:
var id = (from u in myDb.TBL_TRANSAKSI_MKN_MNMs
where u.GL_TRANSAKSI.Value.Date.Equals(dateTimePicker1.Value.Date)
join l in myDb.TBL_DETAIL_TRANSAKSIs on u.ID_NOTA equals l.ID_NOTA
//into g1
join m in myDb.TBL_MKN_MNMs on l.ID_MKN_MNM equals m.ID_MKN_MNM
//into g
group new {u,l,m} by new {u.TGL_TRANSAKSI, m.NAMA_MKN_MNM, m.HARGA_JUAL, l.ID_MKN_MNM, u.USERNAME}
into grp
select new MyClass
{
MakanMinum = grp.Key.NAMA_MKN_MNM,
HargaJual = grp.Key.HARGA_JUAL,
sumStok = grp.Sum(groupedthing => groupedthing.l.ID_MKN_MNM),
Tanggal = grp.Key.TGL_TRANSAKSI,
Jumlah = grp.Key.HARGA_JUAL * grp.Sum(groupedthing => groupedthing.l.ID_MKN_MNM),
Total = grp.Sum(grouptotal => grp.Key.HARGA_JUAL * grp.Sum(groupedthing => groupedthing.l.ID_MKN_MNM)),
Username = grp.Key.USERNAME
});
class MyClass
{
public string MakanMinum {get;set;}
.....
}

Related

Unable to Convert Linq to Lambda Notation

public ActionResult EditArticle(int id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var typeId = 0;
var catId = 0;
var subCatId = 0;
var viewModel = (from sa in ems.SupportArticles
join ssc in ems.SupportSubCategories on sa.SubCatID equals ssc.SubCatID
join sc in ems.SupportCategories on ssc.CatID equals sc.CatID
join st in ems.SupportTypes on sc.TypeID equals st.TypeID
where sa.ArcticleId == id
select new SupportArticleViewModel { supportArticle = sa, supportSubCat = ssc, supportCat = sc, supportType = st });
foreach (var vm in viewModel)
{
typeId = vm.supportType.TypeID;
catId = vm.supportCat.CatID;
subCatId = vm.supportSubCat.SubCatID;
}
I want to convert it into Lambda Notation.But, I am unable to do it.Please help.I am using SupportViewModel which contains property of SupportType,SupportCategory ,SupportSubCategoryand SupportArticle.
Following is functional way do query , you have to make use of join function and than you get data
var filteredArtciles = SupportArticles.Where(sa=> sa.ArcticleId == id);
var query =
SupportArticles.
Join(SupportSubCategories,sa => sa.SubCatID ,ssc => ssc.SubCatID,(sa, ssc) => new {sa,ssc}).
Join(SupportCategories,sassc => sassc.ssc.CatID ,sc=>sc.CatID ,(sassc, sc) => new {sassc,sc}).;
Join(SupportTypes,sasscsc => sasscsc.sc.TypeID ,st=>st.TypeID ,(sc, st) => new {sasscsc,st}).
Select(j=>
new SupportArticleViewModel
{
supportArticle = j.sasscsc.sassc.sa,
supportSubCat = j.sasscsc.sassc.ssc,
supportCat = j.sasscsc.sc,
supportType = j.st
}
));

Linq to Entities - where statement throws System.NotSupported Exception

var entity =
from document in db.Context.DocumentEntity
join product in db.Context.ProductEntity on document.ProductId equals product.Id
join partner in db.Context.PartnerEntity on product.PartnerId equals partner.Id
select new
{
document,
product,
partner
} into t1
where request.PartnerFilter.Contains(t1.partner.Name)
group t1 by t1.document.Date into rp
select new
{
PartnerName = rp.FirstOrDefault().partner.Name,
Date = rp.FirstOrDefault().document.Date,
Income = rp.Sum(x => x.document.Income),
Click= rp.Sum(x => x.document.Click)
};
result = ToDataTable(entity.OrderByDescending(d=>d.Date).ToList());
public static DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType);
dataTable.Columns.Add(prop.Name, type);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
The problem is on where clause. request.PartnerFilter is a string array and might be null. I need to check if partner.Name is included in it. Kind of Sql Where-In. In the end entity.ToList() throws System.NotSupported Exception. How can I accomplish to filter?
If you want to use Contains inside the EF query expression tree, you need to ensure the variable is not null. And you need to do that (along with the condition if it needs to be applied) outside the query.
For instance:
var partnerFilter = request.PartnerFilter ?? Enumerable.Empty<string>();
bool applyPartnerFilter = partnerFilter.Any();
var entity =
...
where (!applyPartnerFilter || partnerFilter.Contains(t1.partner.Name))
...
But in my opinion it would be much better to apply the optional filter(s) outside the query, for instance:
var partners = db.Context.PartnerEntity.AsQueryable();
if (request.PartnerFilter != null && request.PartnerFilter.Any())
partners = partners.Where(partner => request.PartnerFilter.Contains(partner.Name));
var entity =
...
join partner in partners on product.PartnerId equals partner.Id
...
(no where)
Take this request part out of the equation because Entity Framework doesn't know what to do with a Request object, it can handle strings, string arrays, etc.
string[] strArray=request.PartnerFilter;
var entity =
from document in db.Context.DocumentEntity
join product in db.Context.ProductEntity on document.ProductId equals product.Id
join partner in db.Context.PartnerEntity on product.PartnerId equals partner.Id
select new
{
document,
product,
partner
} into t1
//Check if null
where strArray!=null && strArray.Any() && strArray.Contains(t1.partner.Name)
group t1 by t1.document.Date into rp
select new
{
PartnerName = rp.FirstOrDefault().partner.Name,
Date = rp.FirstOrDefault().document.Date,
Income = rp.Sum(x => x.document.Income),
Click= rp.Sum(x => x.document.Click)
};
Also, use Navigation Properties instead of joins
You use the SQL WHERE IN () Clause with Contains correct. Your only problem is the possible null exception.
What should happen if the array is empty? Would you like to have all the values? Use true if array is null otherwise false
Try this:
string[] partnerNames = request.PartnerFilter;
var entity =
from document in db.Context.DocumentEntity
join product in db.Context.ProductEntity on document.ProductId equals product.Id
join partner in db.Context.PartnerEntity on product.PartnerId equals partner.Id
select new
{
document,
product,
partner
} into t1
where partnerNames?.Contains(t1.partner.Name) ?? true
group t1 by t1.document.Date into rp
select new
{
PartnerName = rp.FirstOrDefault().partner.Name,
Date = rp.FirstOrDefault().document.Date,
Income = rp.Sum(x => x.document.Income),
Click= rp.Sum(x => x.document.Click)
};
WHERE IN - as query Syntax
var selected = from document in Document
where new[] {"Paul", "Peter"}.Contains(document.UserName)
select document
WHERE IN - as method Syntax
var selected = Document
.Where(d => new[] ["Paul","Peter"}.Contains(d.UserName))

linq join, group by to get count of child table

After getting my join to work I seem to have gotten stuck on the count bit.
What I am attempting below is get a count of documents printed based on the join below.
What would the code be to get the count per 'guardiandocsrequired'?
var guardianEntityType = new {EntityTypeFK = "GUARDIAN"};
return (from d in dbContext.GuardianDocsRequireds
join p in dbContext.DocumentPrintingLogs on
new { docTypeFK = d.DocTypeFK, entityFK = d.GuardianFK } equals
new { docTypeFK = p.DocTypeFK, entityFK = p.EntityFK }
where d.GuardianFK == entityPK && p.ItemGroupFK == itemGroupID && p.EntityTypeFK == "GUARDIAN"
group d by new
{
d.GuardianFK,
d.DocTypeFK,
d.DocumentType.DocTypeDescription,
d.RequiredStatus
}
into res
select new DocumentsRequired
{
EntityPK = res.Key.GuardianFK,
EntityType = entityType,
DocTypeFK = res.Key.DocTypeFK,
DocTypeDescription = res.Key.DocTypeDescription,
RequiredStatus = res.Key.RequiredStatus,
PrintCount = ???
}
).ToList();
If it helps, I have written the sql to produce exactly what I require as follows:
SELECT gdr.DocRequiredID,gdr.RequiredDate,gdr.GuardianFK,gdr.DocTypeFK,gdr.RequiredStatus,
COUNT(dpl.DocPrintedID) AS documentsPrinted
FROM dbo.GuardianDocsRequired gdr
LEFT OUTER JOIN dbo.DocumentPrintingLog dpl ON gdr.DocTypeFK = dpl.DocTypeFK
AND gdr.GuardianFK = dpl.EntityFK
AND dpl.EntityTypeFK = 'GUARDIAN'
WHERE gdr.GuardianFK = #entityPK
GROUP BY gdr.DocRequiredID,gdr.RequiredDate,gdr.GuardianFK,gdr.DocTypeFK,gdr.RequiredStatus
Do you mean sth like this?
var guardiandocsrequired = (from d in dbContext.GuardianDocsRequireds
join p in dbContext.DocumentPrintingLogs on
new { docTypeFK = d.DocTypeFK, entityFK = d.GuardianFK } equals
new { docTypeFK = p.DocTypeFK, entityFK = p.EntityFK }
where d.GuardianFK == entityPK && p.ItemGroupFK == itemGroupID && p.EntityTypeFK == "GUARDIAN"
group d by new
{
d.GuardianFK,
d.DocTypeFK,
d.DocumentType.DocTypeDescription,
d.RequiredStatus
}
into res
select new DocumentsRequired
{
EntityPK = res.Key.GuardianFK,
EntityType = entityType,
DocTypeFK = res.Key.DocTypeFK,
DocTypeDescription = res.Key.DocTypeDescription,
RequiredStatus = res.Key.RequiredStatus,
PrintCount = ???
}
).ToList();
int cnt = guardiandocsrequired.Count;
return guardiandocsrequired;

DataTable group the result in one row

I have a DataTable and want to group Name, LastName and Comment. The rest should be in the same row.
In my Code firstly i make ID's values as header and then organize the Attribute values to each ID. What I want here is to group the the same Name, Lastname and Comment with their ID values.
My first Table looks like that:
ID Name Lastmame Comment Attribute
1 kiki ha hello FF
3 lola mi hi AA
2 ka xe what UU
2 kiki ha hello SS
After I use my code:
Name Lastname Comment 1 3 2
kiki ha hello FF
lola mi hi AA
ka xe what UU
kiki ha hello SS
What I want to have is:
Name Lastname Comment 1 3 2
kiki ha hello FF SS
lola mi hi AA
ka xe what UU
My Code:
DataTable table1 = new DataTable("Kunde");
table1.Columns.Add("Comment", typeof(String));
table1.Columns.Add("Name", typeof(String));
table1.Columns.Add("Lastname", typeof(String));
DataTable comment = new DataTable("Comment");
comment.Columns.Add("ID", typeof(String));
comment.Columns.Add("Comment", typeof(String));
comment.Columns.Add("Attribute", typeof(String));
DataSet ds = new DataSet("DataSet");
ds.Tables.Add(table1);
ds.Tables.Add(comment);
object[] o1 = { "hello", "kiki", "ha" };
object[] o2 = { "hi", "lola", "mi" };
object[] o3 = { "what", "ka", "xe" };
object[] c1 = { 1, "hello", "FF" };
object[] c2 = { 3, "hi", "AA" };
object[] c3 = { 2, "what", "UU" };
object[] c4 = { 2, "hello", "SS" };
table1.Rows.Add(o1);
table1.Rows.Add(o2);
table1.Rows.Add(o3);
comment.Rows.Add(c1);
comment.Rows.Add(c2);
comment.Rows.Add(c3);
comment.Rows.Add(c4);
var results = from tb1 in comment.AsEnumerable()
join tb2 in table1.AsEnumerable()
on tb1.Field<string>("Comment") equals tb2.Field<string>("Comment")
select new
{
ID = tb1.Field<String>("ID"),
Name = tb2.Field<String>("Name"),
Lastname = tb2.Field<String>("Lastname"),
Comment = tb1.Field<String>("Comment"),
Attribute = tb1.Field<String>("Attribute"),
};
DataTable result = LINQToDataTable(results);
var products = result.AsEnumerable()
.GroupBy(c => c["ID"])
.Where(g => !(g.Key is DBNull))
.Select(g => (string)g.Key)
.ToList();
var newtable = result.Copy();
products.ForEach(p => newtable.Columns.Add(p, typeof(string)));
foreach (var row in newtable.AsEnumerable())
{
if (!(row["ID"] is DBNull)) row[(string)row["ID"]] = row["Attribute"];
}
newtable.Columns.Remove("ID");
newtable.Columns.Remove("Attribute");
var result11 = from t1 in newtable.AsEnumerable()
group t1 by new { Name = t1.Field<String>("Name"), LastName = t1.Field<String>("LastName"), Comment = t1.Field<String>("Comment"), } into grp
select new
{
Name = grp.Key.Name,
LastName = grp.Key.LastName,
Comment = grp.Key.Comment,
//Something here
};
LINQToDataTable method definition
using System.Reflection;
public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
DataTable dtReturn = new DataTable();
// column names
PropertyInfo[] oProps = null;
if (varlist == null) return dtReturn;
foreach (T rec in varlist)
{
if (oProps == null)
{
oProps = ((Type)rec.GetType()).GetProperties();
foreach (PropertyInfo pi in oProps)
{
Type colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()
== typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
}
DataRow dr = dtReturn.NewRow();
foreach (PropertyInfo pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
Based on the comments to this other answer:
One approach would be to stuff all the variable columns in a structure (like a dictionary).
In order to do this, use the following query:
var variableColumnNames = newtable.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.Except(new[]{"Name", "Lastname", "Comment"});
var result11 = from t1 in newtable.AsEnumerable()
group t1 by new
{
Name = t1.Field<String>("Name"),
LastName = t1.Field<String>("LastName"),
Comment = t1.Field<String>("Comment"),
} into grp
select new
{
grp.Key.Name,
grp.Key.LastName,
grp.Key.Comment,
Values = variableColumnNames.ToDictionary(
columnName => columnName,
columnName => grp.Max(r => r.Field<String>(columnName)))
};
If you really need to have a variable number of properties in the class, this is not possible as far as I know, so the only plausible way to do that is to output the result to another DataTable (to which we can add as many columns as we want).
Approach #2 - using dynamic
The LINQ query:
var result11 = from t1 in newtable.AsEnumerable()
group t1 by new
{
Name = t1.Field<String>("Name"),
LastName = t1.Field<String>("LastName"),
Comment = t1.Field<String>("Comment"),
} into grp
select CreateNewDynamicObject
(
grp.Key.Name,
grp.Key.LastName,
grp.Key.Comment,
variableColumnNames.ToDictionary(
columnName => columnName,
columnName => grp.Max(r => r.Field<String>(columnName)))
);
}
the new method that creates the dynamic object:
private static dynamic CreateNewDynamicObject(
string name, string lastName, string comment, Dictionary<string, string> customProperties)
{
dynamic obj = new ExpandoObject();
obj.Name = name;
obj.LastName = lastName;
obj.Comment = comment;
foreach (var prop in customProperties)
(obj as IDictionary<string, Object>).Add(prop.Key, prop.Value ?? "");
return obj;
}
Approach #3 - outputting to a DataTable
The resulting DataTable (destinationTable) can be used as a source for a DataGridView:
var destinationTable = new DataTable();
foreach (var column in newtable.Columns.Cast<DataColumn>())
destinationTable.Columns.Add(column.ColumnName, typeof(String));
var result11 =
from t1 in newtable.AsEnumerable()
group t1 by new
{
Name = t1.Field<String>("Name"),
LastName = t1.Field<String>("Lastname"),
Comment = t1.Field<String>("Comment"),
}
into grp
select
variableColumnNames.ToDictionary(
columnName => columnName,
columnName => grp.Max(r => r.Field<String>(columnName)))
.Concat(new Dictionary<string, string>
{
{"Name", grp.Key.Name},
{"Lastname", grp.Key.LastName},
{"Comment", grp.Key.Comment}
}
).ToDictionary(x => x.Key, x => x.Value);
foreach (var row in result11)
{
var newRow = destinationTable.NewRow();
foreach (var columnName in newtable.Columns.Cast<DataColumn>().Select(c => c.ColumnName))
newRow[columnName] = row[columnName];
destinationTable.Rows.Add(newRow);
}

how convert DataTable to List<String> in C#

I am using C# Linq now I am converting DataTable to List
and I am getting stuck...
give me right direction thanks..
private void treeview1_Expanded(object sender, RoutedEventArgs e)
{
coa = new List<string>();
//coa = (List<string>)Application.Current.Properties["CoAFull"];
HMDAC.Hmclientdb db = new HMDAC.Hmclientdb(HMBL.Helper.GetDBPath());
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset, a.Category, a.CoAName, a.Hide, a.Recurring, a.TaxApplicable });
DataTable dtTable = new DataTable();
dtTable.Columns.Add("Asset", typeof(bool));
dtTable.Columns.Add("Category", typeof(string));
dtTable.Columns.Add("CoAName", typeof(string));
dtTable.Columns.Add("Hide", typeof(bool));
dtTable.Columns.Add("Recurring", typeof(bool));
dtTable.Columns.Add("TaxApplicable", typeof(bool));
if (data.Count() > 0)
{
foreach (var item in data)
{
DataRow dr = dtTable.NewRow();
dr["Asset"] = item.Asset;
dr["Category"] = item.Category;
dr["CoAName"] = item.CoAName;
dr["Hide"] = item.Hide;
dr["Recurring"] = item.Recurring;
dr["TaxApplicable"] = item.TaxApplicable;
dtTable.Rows.Add(dr);
}
}
coa = dtTable;
}
It seems that you already have a strongly typed list. Why converting this to a weakly typed DataTable and then back to a list?????
var data =
from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new
{
a.Asset,
a.Category,
a.CoAName,
a.Hide,
a.Recurring,
a.TaxApplicable
};
var list = data.ToList();
If you want to be able to use this list outside the scope of the method, define a type that will hold the different properties and in your select statement use this type instead of the anonymous type like:
var data =
from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new MyType
{
Asset = a.Asset,
Category = a.Category,
CoAName = a.CoAName,
Hide = a.Hide,
Recurring = a.Recurring,
TaxApplicable = a.TaxApplicable
};
List<MyType> list = data.ToList();
You don't need the data table according to the code you have displayed:
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset.ToString() + a.Category.ToString()
+ a.CoAName.ToString()... }).ToList();
If you really want to convert your datatable to a 1D list, you can do it like this
foreach (DataRow row in dtTable.Rows)
{
foreach (DataColumn col in dtTable.Columns)
{
coa.Add(row[col]);
}
}
As you are using Select new in you linq query It will find object. What you can do is
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset, a.Category, a.CoAName, a.Hide, a.Recurring, a.TaxApplicable });
this is your query and you select multiple columns in your query. So you can't convert your data to a single List of string. What you can do is concatenate all the column in a single string and then add them in a list of string.
To do that modify your query like 'CK' said
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset.ToString() + a.Category.ToString()
+ a.CoAName.ToString()... }).ToList();
And then do
List<string> name = new List<string>(data.ToList());

Categories

Resources