Convert SQL query to LINQ to get column value as xml string - linq

I have following query in SQL.
I have to write the same query in LINQ which will give the same output as SQL query in XML string format.
This select statement is returning column value as XML
SELECT Student.Name
FROM StudentCategoryAssociation Assoc
JOIN Student ON Assoc.CategoryId = Student.Id
for xml raw('Category'), root('StudentCategories'), type
output of this is:
<StudentCategories>
<Category Name="StudentCategory" />
<Category Name="Light" />
</StudentCategories>

It might have to bit more than a simple Linq to get the desired output.I have tried to mock your db with List in following examples.
var result = new StudentCategories
{
Category = associationList
.Join(studentlist,
a=>a.Id,
s=>s.Id,
(a,s)=>new Category{Name=s.Name}).ToList()
};
var serializer = new XmlSerializer(typeof(StudentCategories));
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var settings = new XmlWriterSettings{OmitXmlDeclaration = true,Indent=true};
string xmlString;
using(var sww = new StringWriter())
using(XmlWriter writer = XmlWriter.Create(sww,settings))
{
serializer.Serialize(writer, result,emptyNamespaces);
xmlString = sww.ToString(); // Your XML
}
Where Categories and StudentCategories are defined as
[XmlRoot(ElementName="Category")]
public class Category {
[XmlAttribute(AttributeName="Name")]
public string Name { get; set; }
}
[XmlRoot(ElementName="StudentCategories")]
public class StudentCategories {
[XmlElement(ElementName="Category")]
public List<Category> Category { get; set; }
}
The output would be
<StudentCategories>
<Category Name="StudentCategory" />
<Category Name="Light" />
</StudentCategories>

Related

SELECT result map to entity in Dynamic Linq in Entity Framework Core

I have a Linq query which is selecting 2 columns(that can be any 2 from all columns) dynamically based on some condition.I need to map the query result in to below model irrespective of selected column names
public class FinalModel
{
public string Text { get; set; }
public string Id { get; set; }
}
Currently I am using reflection to map the result in to that model because i am getting some anonymous list of objects and it is working fine, But I want to remove that reflection and need to add the mapping in the select itself, my current implementation is like below
string column1 = "Name" //can be other columns also
string column2 = "Age"
var result = _context.table1
.Select("new ("+ column1 +","+ column2 +")")
.Distinct()
.Take(10) // having more records in table
.ToDynamicList()
.Select(x => new FinalModel()
{
Id = x.GetType().GetProperty(column1).GetValue(x).ToString(),
Text = x.GetType().GetProperty(column2).GetValue(x).ToString(),
});
The above code is working fine but I need to remove the below section
.Select(x => new FinalModel()
{
Id = x.GetType().GetProperty(column1).GetValue(x).ToString(),
Text = x.GetType().GetProperty(column2).GetValue(x).ToString(),
});
Is there any way to remove the refletion and add that model mapping directly inside Select("new (column1,column2)")
Is there any way to add orderBy with Column2 variable?
You can use generic versions of Select and ToDynamicList and OrderBy($"{column2}") for sorting:
var result = _context.table1
.Select<FinalModel>($"new ({column1} as Id, {column2} as Text)")
.Distinct()
.OrderBy("Text")
.Take(10)
.ToDynamicList<FinalModel>();
Or if you want to stick with dynamic:
var result = _context.table1
.Select($"new ({column1}, {column2})")
.Distinct()
.OrderBy($"{column2}")
.Take(10)
.ToDynamicList()
.Select(d => new FinalModel()
{
Id = d[column1].ToString(),
Text = d[column2].ToString(),
})
.ToList();
You need to use .Select<T> instead of just .Select() to make sure that the selected entity the correct type. So in your case you need .Select<FinalModel>.
Use the as cast operator to "rename" the properties from the source-entity to the destination entity (FinalModel)
If you want the result to be typed, also use .ToDynamicList<FinalModel>().
Full example code below:
using System.Linq.Dynamic.Core;
class Program
{
static void Main(string[] args)
{
var myQuery = new[] { new XModel { Age = "1", Name = "n" } }.AsQueryable();
string column1 = "Name";
string column2 = "Age";
var result = myQuery
.Select<FinalModel>("new (" + column1 + " as Id, " + column2 + " as Text)")
.Distinct()
.Take(10)
.ToDynamicList<FinalModel>();
Console.WriteLine(result[0].Id + " " + result[0].Text);
}
public class XModel
{
public string Name { get; set; }
public string Age { get; set; }
}
public class FinalModel
{
public string Text { get; set; }
public string Id { get; set; }
}
}

Concatenate Datetime and string and bind result to dropdownlist using Json method

I want to concatenate DateTime field and string field in MVC application.
I want Linq to Entities query to solve this. Here is my SQL query which I want in Linq.
Select accountid,TourID, ' ('+ convert(nvarchar(20), fromdate ,105) +')' + purpose as TourDetails
from Tour
where AccountID=#AccID;
As shown in above query I want to concat fromdate and purpose. I want to pass result of this query as JSON result.
Something like this:
public class Tour
{
public int accountid { get; set; }
public int TourID { get; set; }
public DateTime date { get; set; }
public string purpose { get; set; }
}
var t = new List<Tour>
{
new Tour
{
accountid = 1,
TourID = 2,
date = DateTime.Now,
purpose = "Testing"
}
};
var output = t.Where(c => c.accountid == accId).Select(k => new
{
accountid = k.accountid,
TourID = k.TourID,
TourDetails = k.date.ToString() + k.purpose
}).ToList();
var o = JsonConvert.SerializeObject(output);
You can use something like this if you're in a MVC Controller requiring an ActionResult as output :
//here 'context' is your DbContext implementation and Tours is your DbSet.
var TourDetails= context.Tours.Where(t=>t.AccountID==_AccID)
.Select(s=>new {
AccountID = s.accountid,
TourID = s.TourID,
//s.fromdate.ToString("yyyyMMddHHmmss") use this to format your date if needed
TourDetails = s.fromdate.ToString() + s.purpose
})
.ToList();
//JsonRequestBehavior.AllowGet only if your not using POST method
return Json(TourDetails, JsonRequestBehavior.AllowGet);

The entity or complex type 'AdventureWorks2012Model.Product' cannot be constructed in a LINQ to Entities query

As you can see, I got this error when I built Data Gird using Kendo UI. Does anybody could point out where I'm wrong in my code below.
private IEnumerable<Product> GetSubProduct()
{
var context = new AdvenDBEntities();
var subcate = context.Products.Select(p => new Product
{
ProductID = p.ProductID,
Name = p.Name,
Color = p.Color,
ListPrice = p.ListPrice,
}).ToList();
return subcate;
}
Error:
The entity or complex type 'AdventureWorks2012Model.Product' cannot be constructed in a LINQ to Entities query.
Thank you so much for your time!
Since Product is an entity of model, you are creating new object of this entity while selecting the records, which is NOT good idea, I am NOT sure how model will handle this kind of behaviour that is why it is preventing you to do so, (I guess). Anyway you can change the code to this,
private IEnumerable<Product> GetSubProduct()
{
var context = new AdvenDBEntities();
var subcate = context.Products.ToList();
return subcate;
}
BTW your function name indicating that you are missing a Where clause.
Also you can create some custom DTO class and use it instead.
E.g.
class ProductDTO
{
public int ProductID { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public decimal ListPrice { get; set; }
}
private IEnumerable<ProductDTO> GetSubProduct()
{
var context = new AdvenDBEntities();
var subcate = context.Products.Select(p => new ProductDTO
{
ProductID = p.ProductID,
Name = p.Name,
Color = p.Color,
ListPrice = p.ListPrice,
}).ToList();
return subcate;
}
The first bad smell code I can point out for you. DBContext implements IDisposable so you are responsible for calling Dispose on it. In all, but one case in here, using block
You must build query to get all the product and then extract from it.
private IEnumerable<Product> GetSubProduct()
{
using (var context = new AdvenDBEntities())
{
// Get all constructed type product and then select from it
var subcate = context.Products
.ToList()
.Select(p => new Product
{
ProductID = p.ProductID,
Name = p.Name,
Color = p.Color,
ListPrice = p.ListPrice,
});
return subcate;
}
}

How to convert LINQ query result to list and return generic List?

I used generic ORM list
example.
This is my table.
Person table
Guid
Name
LastName
and this is my struct class.
public struct PersonItem // database and class field names are the same
{
public Guid Guid{ get; set; }
public string Name { get; set; }
public string LastName { get; set; }
}
public struct PersonItems
{
public PersonItems()
{
Items = new List<PersonItem>();
}
public List<PersonItem> Items { get; set; }
}
I'm using such and no problem but I always have to write field's
public PersonItems GetPersons()
{
var query = (from p in _DbEntities.t_Crew
select p).ToList();
if (query != null)
{
foreach (var item in query)
{
_PersonItems.Items.Add(new PersonItem
{
Guid = item.Guid,
Name = item.Name,
LastName = item.LastName
});
}
}
return _PersonItems;
}
public PersonItems GetPersons()
{
PersonItems personItems = new PersonItems();
var query = from p in _DbEntities.t_Person
select p; >> this here query I need to convert linq query result to list
personItems = query.ToList();
return personItems ;
}
error
Cannot implicitly convert type System.Collections.Generic.List' to PersonData.PersonItems'.
Try this
public PersonItems GetPersons()
{
PersonItems personItems = new PersonItems();
var query = (from p in _DbEntities.t_Person
select new PersonItems
{
test = p.SomeName,
//Other Stuff
//...
}).ToList();
return query;
}
Comparing to the other version of your GetPersons() method, I think this line :
personItems = query.ToList();
should've been this way instead :
personItems.Items = query.ToList();
Update regarding the latest error. You can't assign list of t_Person to Item property which is of type list of PersonItem. Hence, your query need to be adjusted to return list of PersonItem :
var query = from p in _DbEntities.t_Person
select new PersonItem
{
Guid = p.Guid,
Name = p.Name,
LastName = p.LastName
};
or other option is to change definition of Item property to list of t_Person :
public List<t_Person> Items { get; set; }
Cannot implicitly convert type System.Collections.Generic.List' to PersonData.PersonItems'
Above error says that you are trying to convert generic list to PersonItems.
So at this line, query.ToList() code returns List<PersonItem> not the PersonItems
var query = from p in _DbEntities.t_Person
select p; >> this here query I need to convert linq query result to list
personItems = query.ToList();
return personItems ;
So thats the reason above line of code fails.
What about this?
Change .ctor of PersonItems:
public struct PersonItems
{
public PersonItems(List<PersonItem> items)
{
Items = items;
}
public List<PersonItem> Items { get; set; }
}
And then method GetPersons():
public PersonItems GetPersons()
{
return new PersonItems(_DbEntities.t_Person.ToList());
}

Wrong selection from database using Entity Framework

I have a method that selects two fields from database where text in first field match some value
public static List<List<string>> SelectForSearch(string letter)
{
var data = (from p in model.City
where p.Name.StartsWith(letter)
select new List<string> { p.Name, p.CountryName }).ToList();
return data;
}
But it returns me a list like this:
[0][0]Australia
[0][1]Ballina
[1][0]Berry
[1][1]Australia
[2][0]Australia
[2][1]Bendigo
...
Country and City possition don't have a static index like this:
[0][0]Ballina
[0][1]Australia
[1][0]Berry
[1][1]Australia
[2][0]Bendigo
[2][1]Australia
...
Your issue is that in your select statement, instead of creating a type with Name and CountryName you are creating a List of strings. The List initialiser allows you to pass in the values when the list is constructed by placing them in { } and you are using this ability by accident, as you saw it creates a list of strings where the name is the first element and the country name is the second element. What you want to be doing is more like:
var data = (from p in model.City
where p.Name.StartsWith(letter)
select new { City = p.Name, CountryName = p.CountryName }).ToList();
return data;
This is using anonymous types which is not good as you want to declare a type for the return value. So you should really create a class for storage, for example:
public class CityCountryPair
{
public String City { get; set; }
public String CountryName { get; set; }
}
then your method becomes
public static List<CityCountryPair> SelectForSearch(string letter)
{
var data = (from p in model.City
where p.Name.StartsWith(letter)
select new CityCountryPair() { City = p.Name,
CountryName = p.CountryName
}).ToList();
return data;
}

Resources