Saving FlowDocument to SQL Server - 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/

Related

Change CheckCharacters on XmlReader generated by SqlCommand.ExecuteXmlReader

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.

Retrieve image from Database in winform

I want to retrieve data from database but i'm not able to retrieve image.I've taken TmagePath Datatype as nvarchar
PFB
First you must consider that the datatype in your Database of image must be VarBinary. Than try this:
var filename = ds.Tables[0].Rows[0];
byte[] getImg = new byte[0];
getImg = (byte[])filename["WImagepath"];
MemoryStream stream = new MemoryStream(getImg);
Picwaiter.Image = Image.FromStream(stream);
Maybe usefull answer:
https://stackoverflow.com/a/29589703/5603115

Printing RTF with headers and footers - FlowDocument or something else?

I've been looking at importing an RTF into a flowdocument, obstinately for the purposes of unattended printing; after a lot of poking, using a FlowDocument seemed to be the right approach. I've got the RTF to generally work, however footers disappear when loading the RTF into a FlowDocument.
The RTF was generated in Word, and when loaded into Wordpad, the footers are visible, so I can only assume I'm loading the document wrong, or it's an issue with the default paginator, or possibly both.
This is what I have so far, which loads the file and does the printing:
[STAThread]
public static int Main(string[] args)
{
var documentPath = #"C:\temp\Example.rtf";
var fileStream = File.Open(documentPath, FileMode.Open, FileAccess.Read, FileShare.Read);
// Load the RTF into the flow document
var flowDocument = new FlowDocument();
TextRange textRange = new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd);
textRange.Load(fileStream, DataFormats.Rtf);
flowDocument.ColumnWidth = double.PositiveInfinity;
var t = new Thickness(72);
flowDocument.PagePadding = t; // Page margin
// Get printer
var queue = LocalPrintServer.GetDefaultPrintQueue();
var capa = queue.GetPrintCapabilities();
// Configure paginator
var paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator;
paginator.PageSize = new Size(capa.OrientedPageMediaWidth.Value, capa.OrientedPageMediaHeight.Value);
// ...and print.
var writer = System.Printing.PrintQueue.CreateXpsDocumentWriter(queue);
writer.Write(paginator);
return 0;
}
...beyond that, I'm at a loss. It's not clear whether the footers simply haven't loaded (and thus aren't part of the FlowDocument) - I suspect this is the case as we're loading into a TextRange that marks the start and end of the main FlowDocument content; but I'm also suspecting I might need a custom paginator as well.
Are there any pointers to the docs I'm missing - a google search for "RTF footer import flowdocument paginator" (and similar) has (so far) revealed no pertinent results. The closest I've so far found is this SO question, but this doesn't cover fetching the header/footer from an RTF file.
Take a look at this MSDN blogpost they are doing almost the same you are doing. With a custom DocumentPaginator to scale the the original pages. I think this should do the trick. I also used it a long time ago and headers and footers were no problem.
To provide the header and footer property during printing, we usually handle the PrintPage event and provide these features in this event handler. Here is a sample for your reference. Although this sample is a printer class for DataGridView, you can take the logic of add the header and footer features.
· http://www.codeproject.com/KB/cs/DGVPrinter.aspx
If you are using the WebBrowser to print the HTML, you can custom the header and footer like mentioned in the following article.
· http://www.codeproject.com/KB/miscctrl/tips.aspx#tip3.8.2

Is there a way to display a image in WPF stored in memory?

What I got is something like a screenshot making application. (managed to serialize, thank god!!!) When a button is clicked a screenshot is taken by accessing a handling classe's method. now the tricky part is that the class has another method for operating with the above said result, in such a manner than when the respective handling method is called, a window is created(shown) and the bitmap image should go into a display container in that window. The problem is that so far, I've noticed that in WPF the image control's source cannot be attribuited to a variable which stores the image. How can i display the image stored in that variable without having to save it first,get uri,etc. ?
You need to create an image from a memory stream, this has been well documented by many people. Here are two links that may get you started:
http://forums.silverlight.net/forums/p/44637/166282.aspx
http://www.wpftutorial.net/Images.html
thanks for the links slugster. Here's how I did it:
MemoryStream ms = new MemoryStream();
sBmp = gBmp; //note: gBmp is a variable that stores the captured image and passes it on to the method that uses sBMP as a distribuitor of the variable holding the captured image data
//variable that holds image
sBmp.Save(ms,ImageFormat.Bmp);
//my buffer byte
byte[] buffer = ms.GetBuffer();
//Create new MemoryStream that has the contents of buffer
MemoryStream bufferPasser = new MemoryStream(buffer);
//Creates a window with parents classthatholdsthismethod and null
Edit childEdit = new Edit(this, null);
childEdit.Show();
//I create a new BitmapImage to work with
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = bufferPasser;
bitmap.EndInit();
//I set the source of the image control type as the new BitmapImage created earlier.
childEdit.imgImageCanvas.Source = bitmap;
childEdit.Activate();
I've basically combined what I had found on those pages with some info I found on how to pass on a bmp to a memstream. I got this to work 100% :)

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