Transforming data retrieved from LINQ (IQueryable) to XML? - entity-framework

I presume this is possible? Basically i am receiving using LINQ (LINQ2Entities Entity Framework) data and return it to an IQUERYABLE once i this data i need to transform it to XML in a Memory Stream and a physical file on the hard disk - streamwriter??
Does anyone know if this is possible?
Any help really appreciated
Do i need to use LINQtoXML to accomplish this?
Any examples or tutorials anybody knows of would be great.
Thanks again
EDIT
After a little bit of investigation i think i require a XML Serializer for LINQ2Entities / IQueryable??

LINQ to XML is probably the best choice. You can use functional construction to create an XML tree in a single statement, like:
using (ContactEntities context = new ContactEntities()) {
XDocument xml = new XDocument(
new XElement("contacts",
from contact in context.Contacts
orderby contact.ContactId
select new XElement("contact",
new XAttribute("contactId", contact.ContactId),
new XElement("firstName", contact.FirstName),
new XElement("lastName", contact.LastName))));
xml.Save(yourStream);
}

Entity classes are by default Data Contracts, which means that they can be serialized based on the fields they contain:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx

I know this question is a old, but I wanted to show my solution to this problem.
public static string CreateXml<T>(IQueryable<T> thisQueryable)
{
var thisList = thisQueryable.ToList();
var xmlResult = "";
using (var stringWriter = new StringWriter())
{
using (var xmlWriter = new XmlTextWriter(stringWriter))
{
var serializer = new XmlSerializer(typeof(List<T>));
serializer.Serialize(xmlWriter, thisList);
}
xmlResult = stringWriter.ToString();
}
return xmlResult;
}
Basically this just takes your IQueryable<T> and serializes it to XML and returns that XML as a string.
Then you'd basically take that string and....
var xmlDoc = new XmlDocument();
xmlDoc.Load(xmlResult);
Hope this helps for any future visitors.

Related

How to Add a reference between two BsonDocuments using MongoDbClient in C#

I'm trying to add a reference between two BsonDocument in C#, but unfortunately, I don't know and haven't found any documentation that explains how to do it.
Here is my code:
var parent = new BsonDocument( new BsonElement("name","parentTest"));
parent.Add("newField", "test");
var child1 = new BsonDocument( new BsonElement("name","childTest1"));
var child2 = new BsonDocument( new BsonElement("name","childTest2"));
I want to create a reference (one to many) between the parent BsonDocument and the two child documents (child1 and child2).
I have tried to use MongoDbRef, but without success.
Thank you
After reading a lot of documents about the csharp provider without any lead, I have decided to read the php documentation and to follow the following steps:
To create the documents and the reference using the mongodb command
line client
Query the database using the csharp provider and see what kind
of type the BsonDocument will return in the reference values.
Recreate the same structure and see if the command line client
will return the same json string.
I don't know is the official cshap provider have something that performs this for me, but I was unable to find any document explaining how to do it. So I have solved this question by myself. If someone knows an different or easier way to do it, please share your knowlegde here. Thank you all!
As result of my effort, I've created an extension method to make it easier. The code below is such class:
public static class MyMongoDbExtension
{
public static BsonDocument GetDBRef(this BsonDocument document, string collectionName)
{
var id = document.GetValue("_id");
var result = new BsonDocument();
result.Add(new BsonElement("$ref", collectionName));
result.Add(new BsonElement("$id", id));
return result;
}
}

Pull generated HTML programmatically vs. a HttpWebRequest

For our newsletter, I generate the final body of the email in a web page and then want to pull that into the body of the email. I found a way to do that with HttpWebRequest.
private string GetHtmlBody(Guid id)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("http://news.domain.com/News/View/{0}", id.ToString()));
HttpWebResponse responce = (HttpWebResponse)request.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(responce.GetResponseStream());
return sr.ReadToEnd();
}
However, I feel there has to be a better way. Can I somehow pull the generated view without making a web call?
You could use MVCContrib for this task.
Or try to roll some ugly code:
public static string ViewToString(string controlName, object viewData)
{
var vd = new ViewDataDictionary(viewData);
var vp = new ViewPage { ViewData = vd };
var control = vp.LoadControl(controlName);
vp.Controls.Add(control);
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
return sb.ToString();
}
and then:
var viewModel = ...
string template = ViewToString("~/Emails/EmailTemplate.ascx", viewModel);
Assuming the the email code is in the same project as the website, then you should be able to call the action method, get the ActionResult back, then call the ExecuteResult method. The downside is that in order to do it this way, you will need to set it up such that the ExecuteResult will write to a stream that you can take advantage of. In order to do all of this, you will need to mock up some of the classes used by the ControllerContext.
What would probably be a better way (though will likely take more work), is to have the markup you want be generated by an XSLT transform. XSLT is a type of XML document template that can be merged with an XML document that holds data to produce a desired result. If you do this, then you can have your process that sends out emails run the transform as well as have your website run the transform. The advantage of this, is that if you want the markup to be different (i.e. you are redesigning thew newsletter), you will simply need to update the XSLT file and deploy it.
HTH
Finally got a working solution. After finding some proper search terms (thanks to #Darin) any many, many trials I found a solution that works. Putting this in my controller then passing the rendered string into my EmailHelper works great for what I needed.

How to get a list of EntityObject's from an EF model

I need to be able to iterate of a list of EntityObjects that are in an EF model.
For Example..
foreach (System.Data.Objects.DataClasses.EntityObject eObject in ????)
{
}
From what I can see the model context has no such public enumerator.
Anyone ever done this?
The problem here was i needed a dynamic way to iterate over the EntityObjects which are also consider types in the EDMX. I needed to list the Entity name and its properties. Thanks very much to Craig Stuntz for leading me down the right path to solve this issue. Here is the final code i came up with to solve my problem.
EmployeesEntities context = new EmployeesEntities();
MetadataWorkspace workspace = context.MetadataWorkspace;
workspace.LoadFromAssembly(Assembly.Load(#"WindowsFormsApplication10"));
ItemCollection itemCol = workspace.GetItemCollection(DataSpace.OSpace);
StringBuilder sb = new StringBuilder();
foreach (EdmType eType in itemCol)
{
if (eType.GetType().BaseType == typeof(System.Data.Metadata.Edm.EntityType))
{
sb.Append(string.Format("Entity: {0} ", eType.Name));
foreach (EdmProperty prop in
((System.Data.Metadata.Edm.EntityType)(eType)).Properties)
{
sb.Append(string.Format("Property: {0} ", prop.Name));
}
}
}
MessageBox.Show(sb.ToString());
From your comments, I think, despite the code in your question, that you are asking for the list of entity types in the CSDL rather than a list of objects. There's a demo of that here.

EF 4.0 Dynamic Proxies POCO Object Does not match target type

I am using EF 4.0 and POCO's. I stumbled across this error while inserting to records into the data base.
Property accessor 'QualityReasonID' on object 'BI.Entities.QualityReason' threw the following exception:'Object does not match target type.'
There errors occur on the Databind to a GridView after saving a new record to the database. I identified what is happening but I am not sure WHY it is occurring or If I am using EF/POCO's incorrectly. Any insight would be appreciated.
The exception is occuring because the object types in the IEnumerable are not the same.
The orginal entrys in the table are of type System.Data.Entity.DynamicProxies.QualityReason_E483AD567288B459706092F1825F53B1F93C65C5329F8095DD1D848B5D039F04}
While the new one is BI.Entities.QuailtyReason.
Here is how I insert the new object.
public void createQualityReason(QualityReason qReasons)
{
dbcontext.QualityReasons.AddObject(qReasons);
dbcontext.SaveChanges();
}
I resolved the error by changing the fetch code from:
public IEnumerable<QualityReason> fetchQualityReasons()
{
IEnumerable<QualityReason> queryReasons = dbcontext.QualityReasons.AsEnumerable();
return queryReasons;
}
to
public IEnumerable<QualityReason> fetchQualityReasons()
{
IEnumerable<QualityReason> queryReasons = from data in dbcontext.QualityReasons.AsEnumerable()
select new QualityReason
{
QualityReasonID = data.QualityReasonID,
QualityReasonName = data.QualityReasonName
};
return queryReasons;
}
So to get around the error I have to select into the POCO class explicitly each time. This feels like I am going something wrong. Any thoughts?
The error is caused because GridView does not handle polymorphic datasources when using boundfields. So you have two options
Use TemplateFields instead which can handle polymorphic datasources, this may changing some of your front end code and GridView events.
Use Linq to create a non-polymorphic databsource that the boundfields can handle
So instead of using something like ti
gvGroups.DataSource = ProductHelper.Get()
gvGroups.DataBind();
var query = from p in ProductHelper.Get()
select new {p.ProductId, p.ProductName, p.ProductDesc, p.ProductLink};
gvGroups.DataSource = query;
gvGroups.DataBind();
I don't know if the problem has been solved yet, but I've had the same problem with my (POCO) "Scenario" class.
The problem disappeared when using a context.CreateObject<Scenario> to create the (POCO) object i.s.o. a .... = new Scenario().
Faced the same issue today and used Value Injecter to solve it. It's as simple as:
var dynamicProxyMember = _repository.FindOne<Member>(m=>m.Id = 1);
var member = new Member().InjectFrom(dynamicProxyMember) as Member;
That's it :)

Way to automate setting of MergeOptions

I am looking for an automated way to iterate over all ObjectQueries and set the merge option to no tracking (read only context). Once i find out how to do it i will be able to generate a default read only context using a T4 template. Is this possible?
For example lets say i have these tables in my object context
SampleContext
TableA
TableB
TableC
I would have to go through and do the below.
SampleContext sc = new SampleContext();
sc.TableA.MergeOption = MergeOption.NoTracking;
sc.TableB.MergeOption = MergeOption.NoTracking;
sc.TableC.MergeOption = MergeOption.NoTracking;
I am trying to find a way to generalize this using object context.
I want to get it down to something like
foreach(var objectQuery : sc){
objectQuery.MergeOption = MergeOption.NoTracking;
}
Preferably I would like to do it using the baseclass(ObjectContext):
ObjectContext baseClass = sc as ObjectContext
var objectQueries = sc.MetadataWorkspace.GetItem("Magic Object Query Option);
But i am not sure i can even get access to the queries. Any help would be appreciated.
If you wanna do it for all ObjectSet, just one time, for all exection, try this:
var Ctx=YourDbContext;
var objSetProps = Ctx.GetType().GetProperties().Where(prop => prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(ObjectSet<>));
foreach(PropertyInfo objSetProp in objSetProps)
{
ObjectQuery objSet = (ObjectQuery)objSetProp.GetValue(Ctx, BindingFlags.GetProperty, null, null, null);
objSet.MergeOption=MergeOption.NoTracking;
}
I think reflection will be the only choice for this. Something along the lines of:
IEnumerable<ObjectQuery> queries = from pd in context.GetType().GetProperties()
where pd.PropertyType.IsSubclassOf(typeof(ObjectQuery))
select (ObjectQuery)pd.GetValue(context, null);