Change CheckCharacters on XmlReader generated by SqlCommand.ExecuteXmlReader - sql-server

If I try to change CheckCharacters the following way it, reader.Settings.CheckCharacters is still true. How am I supposed to do it?
using (var reader_org = command.ExecuteXmlReader())
{
var settings = new XmlReaderSettings { CheckCharacters = false, ConformanceLevel = ConformanceLevel.Auto };
var reader = XmlReader.Create(reader_org, settings);
reader.Read();
}
According to the documentation it's supposed to work:
"Add features to an existing XML reader. The Create method can accept another XmlReader object. The underlying XmlReader object can be a user-defined reader, a XmlTextReader object, or another XmlReader instance that you want to add additional features to."

It appears you are using FOR XML in SQL Server to generate certain types of XML that are not actually valid values, because they contain restricted characters, and is therefore not valid XML.
SQL Server will quite rightly not allow you to generate such XML if you use the , TYPE directive. But if you do not use that, it generates the XML as a string, and does not validate invalid characters. See also this article.
Ideally, you would use Base64 or similar to encode this. But assuming for whatever reason you don't want to do this, then the reason your current code does not work is that the underlying reader_ord XML reader already has CheckCharacters = true so will throw an exception.
Instead you need to create your own XML reader from the string. Since FOR XML without , TYPE also splits up large XML blobs into separate rows, you also need to concatenate them all first.
var sb = new StringBuilder();
using (var reader = command.ExecuteReader())
{
while (reader.Read()) // read all rows
{
sb.Append(reader.GetString(0));
}
}
var settings = new XmlReaderSettings { CheckCharacters = false, ConformanceLevel = ConformanceLevel.Auto };
using (var xmlReader = XmlReader.Create(sb.ToString(), settings))
{
// do stuff with reader here
}
There are more performant ways to do that: for example you could create your own Stream out of sequential reader.GetStream results, but that is significantly more complex.

Related

Serializing objects Codename One

How do I serialize an object in order to make a customizable Parse initialization? Like:
//Simple text fields to get info
TextField url = new TextField();
TextField appid = new TextField();
TextField clientkey = new TextField();
then I put all in an object e.g:
Myclass object = new Myclass();
object.url = url.getText();
object.appid = appid.getText();
object.clientkey = clientkey.getText();
so I put it here, but before it needs to be serialized in order to keep its values after my app get restarted.
//After serialization
Parse.initialize(object.url, object.appid, object.clientkey);
In this way I can set my Parse initialization by my application instead.
I'd appreciate to see an example of serialization in this case.
When you store an object in parse it's saved locally so you don't need to serialize.
FYI Codename One supports the Externalizable interface to serialize objects in binary form. It also supports seamless externalization for object properties. The latter don't work with Parse AFAIK.
There's no support for serialization. You're on your own.

Dapper: read multiple results with type array not generics

I have a 3 part query that I am reading using QueryMultiple. My problem is on the first Read<T> I need to split the query into 12 different classes, which Dapper does not support from what I could see. Before I used QueryMultiple, my query was only one part and I was using the method from this example Using Dapper to map more than 5 types to get 12 different classes. My question is, how can i split the first Read<T> into twelve classes and then continue with the GridReader? Please note I cannot create one big query.
public static IEnumerable<TReturn> Query<TReturn>(this IDbConnection cnn, string sql, Type[] types, Func<object[], TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null);
UPDATE
I tested this method I added to the Dapper file and it worked, but I was only referencing the DLL and not the actual file in my app so I am not sure how to add this on without taking in the Dapper file from github. I was hoping there was built-in support for what I wanted and I just missed it somewhere in the code. Thanks for any help.
public IEnumerable<TReturn> Read<TReturn>(Type[] types, Func<object[], TReturn> func, string splitOn = "id", bool buffered = true)
{
var identity = this.identity.ForGrid(typeof(TReturn), types, gridIndex);
try
{
foreach (var r in SqlMapper.MultiMapImpl<TReturn>(null, default(CommandDefinition), types, func, splitOn, reader, identity, false))
{
yield return r;
}
}
finally
{
NextResult();
}
}
As i was about to add a pull request i noticed someone was one step ahead of me. Seems this functionality is not included in Dapper right now.
https://github.com/StackExchange/dapper-dot-net/pull/308

EF ObjectQuery<T> Context, Parameters, Connection properties equivalent on DbSet<T>

In the earlier versions of Entity Framework, we were able to reach the Context out of ObjectQuery in order to read Parameters, Connection, etc. as below:
var query = (ObjectQuery<T>)source;
cmd.Connection = (SqlConnection)((EntityConnection)query.Context.Connection).StoreConnection;
cmd.Parameters.AddRange(
query.Parameters.Select(x => new SqlParameter(
x.Name, x.Value ?? DBNull.Value)
).ToArray()
);
When I look at the DbSet<T> object, I am unable to find any equivalent of this. My purpose here is to create extensions which will manipulate the query and get the result out of it.
Here is an instance: http://philsversion.com/2011/09/07/async-entity-framework-queries
Or should I write the extension for DbContext class and work with Set method?
Any idea?
Edit
Here is what I did so far. Basic implementation so far but certainly not ready for production. Any suggestions on this?
public static async Task<IEnumerable<T>> QueryAsync<T>(this DbContext #this, System.Linq.Expressions.Expression<Func<T, bool>> predicate = null)
where T : class {
var query = (predicate != null) ? #this.Set<T>().Where(predicate) : #this.Set<T>();
var cmd = new SqlCommand();
cmd.Connection = (SqlConnection)(#this.Database.Connection);
cmd.CommandText = query.ToString();
if (cmd.Connection.State == System.Data.ConnectionState.Closed) {
cmd.Connection.ConnectionString = new SqlConnectionStringBuilder(cmd.Connection.ConnectionString) {
AsynchronousProcessing = true
}.ToString();
cmd.Connection.Open();
}
cmd.Disposed += (o, e) => {
cmd.Clone();
};
var source = ((IObjectContextAdapter)#this).ObjectContext.Translate<T>(
await cmd.ExecuteReaderAsync()
);
return source;
}
This is a nice workaround, although I don't think you can make it much more generally applicable than what you already have.
A few things to keep in mind:
- Depending on the EF query, e.g. if you are using Include or not, the columns returned in the reader might not match the properties in the type T you are passsing.
- Depending on whether you have inheritance in your model, the T that you pass to translate may not always be the right thing to materialize for every row returned.
- After the task returned by ExecuteReaderAsync completes, you still have to retrieve each row, which depending on the execution plan for the query and the latency you are getting with the server is potentially also a blocking operation.
Async support is not coming to EF in 5.0 but we worked with other teams to make sure we have all the necessary building blocks included in .NET 4.5 and the feature is pretty high in our priority list. I encourage you to vote for it in our UserVoice site.

Saving FlowDocument to SQL Server

I need to save WPF FlowDocuments to SQL Server. What is the best format for doing that? String? Blob? Does it matter in a document less than 5K words or so?
FlowDocument is not serializable so SWeko's answer above will not work.
You can use the methods below to get the FlowDocument to and from a Xaml string which can then be saved in the database using nvarchar(max).
var stringReader = new StringReader(info);
var xmlTextReader = new XmlTextReader(stringReader);
return (FlowDocument)XamlReader.Load(xmlTextReader);
and
var infoString = XamlWriter.Save(info);
If you just want to store the FlowDocument objects in a database, without any processing, I would recommend using binary serialization, and storing the resulting byte array into a varbinary(max). This is fast and scales well.
However, if you already have the FlowDocuments as XML files, than it would be easier just to dump them into a nvarchar(max) field, with no (added) serialization/deserialization overhead. This scales trivially for values under 8k, and then performs kinda OK until you hit around the 10MB mark.
You can serialize FlowDocument using the TextRange class. You can even use the RTF format. Saving:
FlowDocument docToSave; // Lets suppose this var is initialized.
var tr = new TextRange(docToSave.ContentStart,docToSave.ContentEnd);
var dst = new MemoryStream();
tr.Save(dst, DataFormats.Rtf);
dst.Close();
And loading:
FlowDocument docToLoad = new FlowDocument();
var tr = new TextRange(docToLoad.ContentStart,docToLoad.ContentEnd);
Stream src; // Lets suppose it is initialized.
tr.Load(src, DataFormats.Rtf);
src.Close();
See also https://www.wpf-tutorial.com/rich-text-controls/how-to-creating-a-rich-text-editor/

Serializing an object and storing it to a varbinary field in a DB

I can serialize an object to a file using:
var writeStream = File.Open("l.osl", FileMode.Create);
var bformatter = new BinaryFormatter();
bformatter.Serialize(writeStream, l);
What I am trying to do is instead of writing it to a file, write it to a DB varbinary field.
I assume that I have to change writeStream to something else, but what? Can I just put an object in there and there insert that object into the DB (I'm using LINQ).
Will this work?
PS: I have looked around and can't find any solid examples.
Kind of close to this:
Storing C# data structure into a SQL database

Resources