EF Codefirst and RDLC Reports - entity-framework

I'm working on a MVC4 web app with EF 6. I'm using EF code first approach (on a brand new database). So i have the model classes which i use in EF.
Now i need to create some RDLC Reports. To do this i need to create a Dataset. So how can i create a dataset using my model classes? There are relationships between models classes which i need to carry to the dataset.
My ultimate goal is to design and populate data to my report using my ef models.
Thanks in Adance

Generally EF does not support DataSets. If you want to populate DataSets with data loaded with EF then you've got to provide your own functionality for that. Here I present an example how to populate DataTable object from result obtained with query:
public static class IEnumerableExtensions
{
public static DataTable ToDataTable<TEntity>(this IEnumerable<TEntity> entities)
{
DataTable table = new DataTable();
IEnumerable<PropertyInfo> properties = typeof(TEntity)
.GetProperties()
.Where(p => !p.PropertyType.IsClass || p.PropertyType == typeof(string))
foreach(string propertyName in properties.Select( p => p.Name))
{
table.Columns.Add(propertyName);
}
foreach(object item in entities)
{
List<object> propertiesValues = new List<object>();
foreach (PropertyInfo property in properties)
{
propertiesValues.Add(property.GetValue(item));
}
table.Rows.Add(propertiesValues.ToArray());
}
return table;
}
}
You might use then this extension method as follows:
DataTable table = context.People.ToDataTable();
If you want to implement relationships between tables then the logic you have to do will be more complicated. You should use ChildRelations property of DataTable objects to bind them with relations. Then your DataTable objects you might insert into DataSet.

Related

Reporting Services using Entity Framework

I had experience in developing reports(SSRS) using ado.net dataset. Now I am working on an application which is not using ADO.net but entity framework but entity framework does not return datatable or dataset. I want to know
Is there any way to use Collection or custom objects return by entity framework in the reporting services?
Entity framework somehow return datatable or dataset.
Or I should create datatable/dataset from the collection returned by entity framework manually.
For the record, I am getting resultset by executing stored procedure from entity framework.
public void getMyReportData()
{
using (myEntityDataModel v = new myEntityDataModel())
{
var reportQuery = (from r in v.myTable
select new
{
l.ID,
l.LeaveApplicationDate,
l.EmployeeNumber,
l.EmployeeName,
l.StartDate,
l.Col1,
l.Col2,
.......,
.......,
l.Address
}).ToList();
reportViewer1.LocalReport.DataSources.Clear();
ReportDataSource datasource = new ReportDataSource("nameOfReportDataset", reportQuery);
reportViewer1.LocalReport.DataSources.Add(datasource);
Stream rpt = loadEmbededReportDefinition("Report1.rdlc");
reportViewer1.LocalReport.LoadReportDefinition(rpt);
reportViewer1.RefreshReport();
//Another way of setting the reportViewer report source
string exeFolder = Path.GetDirectoryName(Application.ExecutablePath);
string reportPath = Path.Combine(exeFolder, #"rdlcReports\Report1.rdlc");
reportViewer1.LocalReport.ReportPath = reportPath;
reportParameter p = new ReportParameter("DeptID", deptID.ToString());
reportViewer1.LocalReport.SetParameters(new[] { p });
}
}
public static Stream loadEmbededReportDefinition(string reportName)
{
Assembly _assembly = Assembly.GetExecutingAssembly();
Stream _reportStream = _assembly.GetManifestResourceStream("ProjectNamespace.rdlcReportsFolder." + reportName);
return _reportStream;
}
Original source: Creating Reports in ASP.Net with Entity Framework

Updating multiple records using Entity Framework

I am using Entity Framework 5. I am looking for a better approach to update multiple records.
People are talking about EF Extensions. But I am not sure how to use it with my scenario.
This is my method signature.
internal void Update( List<Models.StockItem> stockItemsUpdate)
I need to update all the corresponding stockitem entities.
using (var context = new eCommerceEntities())
{
var items = context.StockItems.Where(si => stockItemsUpdate.Select(it => it.ID).Contains(si.ID));
}
I believe above query will return those entities.
How can I use EF extensions in this scenario?
Thanks.
In EntityFramework.Extended's BatchExtensions there is an Update extension method with this signature:
public static int Update<TEntity>(
this IQueryable<TEntity> source,
Expression<Func<TEntity, TEntity>> updateExpression)
You can use this as follows:
items.Update(item => new StockItem { Stock = 0 });
to set the stock of the selected items to 0.

Tricks to generate List<double> in entity framework as data from similar set of columns

I am developing an silverlight application using WCF and EF.
I am using Database first as our database already exists.
I have a table that consists of 100 columns with datatype real. We want to generate a class which has a List<double> or List<float> instead of that 100 discrete variables in the class for each column.
Is this possible ?? Can someone give me an example?
There's no direct way. What you have to do is use reflection to convert it into a List<double>. Suppose your table names is called MyObject, then EF will generate a class MyObject to represent a row in that table. You can then do:
Type type = typeof(MyObject);
// Get properties (columns) through reflection
PropertyInfo[] properties = type.GetProperties();
List<List<double>> allRows = new List<List<double>>();
using(var dbContext = MyDB.GetContext())
{
foreach(var row in dbContext.MyRows)
{
List<double> columnValues = new List<double>();
foreach (PropertyInfo property in properties)
{
// The sql type REAL will map to either float or double
if(property.PropertyType == typeof(float))
{
columnValues.Add( (double) property.GetValue(row, null) );
}
}
allRows.Add(columnValues);
}
}
Hope you get the idea.

Problem using Include() when serializing Entity Framework 4 POCO classes with WCF

I have a WCF service with an Entity Framework 4 model, using POCO classes that are serialized and sent over to client applications. I have LazyLoadingEnabled and ProxyCreationEnabled set to false, and I'm using Linq to Entites to query an Entity, and return it via List<> to the client. Everything goes perfect when I don't use Include():
public List<TBLTable1> GetTBLTable1(string pCode)
{
using (PcFactoryEntities oPcFactoryDB = new PcFactoryEntities())
{
oPcFactoryDB.ContextOptions.ProxyCreationEnabled = false;
oPcFactoryDB.ContextOptions.LazyLoadingEnabled = false;
var oRS = oPcFactoryDB.TBLTable1
.Where(c => c.Code == pCode).ToList();
XmlObjectSerializer serializer = new DataContractSerializer(typeof(TBLTable1));
serializer.WriteObject(new XmlTextWriter(Console.Out) { Formatting = Formatting.Indented }, oRS[0]);
return oRS;
}
}
After the Linq query, I use the serializer to simulate the serialization process that happens when the POCO class is sent to the client, and I works great. However, when I add an Include() to load one of the navigation list for the class, it starts serializing all of Table2's navigation's list as if LazyLoadingEnabled was set to true, and it goes on forever serializing probably the whole database!
public List<TBLTable1> GetTBLTable1(string pCode)
{
using (PcFactoryEntities oPcFactoryDB = new PcFactoryEntities())
{
oPcFactoryDB.ContextOptions.ProxyCreationEnabled = false;
oPcFactoryDB.ContextOptions.LazyLoadingEnabled = false;
var oRS = oPcFactoryDB.TBLTable1
.Include("TBLTable2")
.Where(c => c.Code == pCode).ToList();
XmlObjectSerializer serializer = new DataContractSerializer(typeof(TBLTable1));
serializer.WriteObject(new XmlTextWriter(Console.Out) { Formatting = Formatting.Indented }, oRS[0]);
return oRS;
}
}
Why is this happening? Shouldn't the LazyLoadingEnabled set to false apply to the class included manually and return all of it's navigation lists to null as it happens with all of the other navigation lists for Table1? Is there a way to fix this so I can return with Table1 some navigations lists filled in with their navigation lists set to null?
Tks
Instead of trying to directly serialize the entity, try projecting to a DTO and serializing that. I agree what your seeing is bizarre behaviour - but it could be that the EF internal graph is taking over when your serializing the entities, but if you serialize a DTO, EF should not intervene.
E.g:
var dto = oPcFactoryDB.TBLTable1
.Where(x => x.Code == pCode)
.Select(x => new SpecialisedDTO
{
PropertyOne = x,
PropertyTwo = x.TBLTable2
}).ToList();
And then serialize that.
Since your projecting, you don't need to eager load - EF will grab what it needs to based on the query you have provided.
It's usually good practice in N-Tier situations to transmit DTO's over the wire, rather than the pure POCO entities.
Do you have a Navigation Property on TBLtable1 to TBLtable2? The .Include() is used to include entities that are linked va FK relationships and the .Include() is passed the Name of the Navigation Property.
So if you have a Person Entity with a NavigationProperty to an Addresses Entity called PersonAddresses you would then execute the following in order to get the Person and their addresses.
var p = dbContext.Person
.Where(x => x.Id == id)
.Include("PersonAddresses")
.SelectFirstOrDefault;

How to relate entities that are not directly mapped through a navigation property

I have an object that has been populated with the contents of four different related entities. However i have another entity in which i cannot include as part of the query due to it not being related in the navigation properites directly to the IQueryable table i am pulling. The entity i am trying to include is related to one of the four different entities that have been included successfully.
Is there a way to include(during db hit or afterwards) this entity as part of the overall object i am creating?
Here is an example of what my calls look like to build the CARTITEM object:
public List<CARTITEM> ListCartItem(Guid cartId)
{
//Create the Entity object
List<CARTITEM> itemInfo = null;
using (Entities webStoreContext = new Entities())
{
//Invoke the query
itemInfo = WebStoreDelegates.selectCartItems.Invoke(webStoreContext).ByCartID(cartId).ToList();
}
//Return the result set
return itemInfo;
}
here is the selectCartItems filter(Where i would normally do the includes):
public static Func<Entities, IQueryable<CARTITEM>> selectCartItems =
CompiledQuery.Compile<Entities, IQueryable<CARTITEM>>(
(cart) => from c in cart.CARTITEM.Include("ITEM").Include("SHIPPINGOPTION").Include("RELATEDITEM").Include("PROMOTION")
select c);
from this i have my CARTITEM object. Problem is i want to include the PROMOTIONTYPE table in this object, but since the CARTIEM entity doesn't have a navigation property directly to the PROMOTIONTYPE table i get an error.
Let me know if you need any more clarification.
Thanks,
Billy
You can use join and if it is the same database and server it should generate the join in SQL and do it all in one call...
LinqToEnties join example