Saving image to database as varbinary, arraylength (part 2) - database

This is a followup to my previous question, which got solved (thank you for that) but now I am stuck at another error.
I'm trying to save an image in my database (called 'Afbeelding'), for that I made a table which excists of:
id: int
souce: varbinary(max)
I then created a wcf service to save an 'Afbeelding' to the database.
private static DataClassesDataContext dc = new DataClassesDataContext();
[OperationContract]
public void setAfbeelding(Afbeelding a)
{
//Afbeelding a = new Afbeelding();
//a.id = 1;
//a.source = new Binary(bytes);
dc.Afbeeldings.InsertOnSubmit(a);
dc.SubmitChanges();
}
I then put a reference to the service in my project and when I press the button I try to save it to the datbase.
private void btnUpload_Click(object sender, RoutedEventArgs e)
{
Afbeelding a = new Afbeelding();
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "JPEG files|*.jpg";
if (openFileDialog.ShowDialog() == true)
{
//string imagePath = openFileDialog.File.Name;
//FileStream fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
//byte[] buffer = new byte[fileStream.Length];
//fileStream.Read(buffer, 0, (int)fileStream.Length);
//fileStream.Close();
Stream stream = (Stream)openFileDialog.File.OpenRead();
Byte[] bytes = new Byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
string fileName = openFileDialog.File.Name;
a.id = 1;
a.source = new Binary { Bytes = bytes };
}
EditAfbeeldingServiceClient client = new EditAfbeeldingServiceClient();
client.setAfbeeldingCompleted +=new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_setAfbeeldingCompleted);
client.setAfbeeldingAsync(a);
}
void client_setAfbeeldingCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error != null)
txtEmail.Text = e.Error.ToString();
else
MessageBox.Show("WIN");
}
However, when I do this, I get the following error:
System.ServiceModel.FaultException: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter :a.
The InnerException message was 'There was an error deserializing the object of type OndernemersAward.Web.Afbeelding.
The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader.'.
Please see InnerException for more details.
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object[] args, IAsyncResult result)
atOndernemersAward.EditAfbeeldingServiceReference.EditAfbeeldingServiceClient.EditAfbeeldingServiceClientChannel.EndsetAfbeelding(IAsyncResult result)
at OndernemersAward.EditAfbeeldingServiceReference.EditAfbeeldingServiceClient.OndernemersAward.EditAfbeeldingServiceReference.EditAfbeeldingService.EndsetAfbeelding(IAsyncResult result)
at OndernemersAward.EditAfbeeldingServiceReference.EditAfbeeldingServiceClient.OnEndsetAfbeelding(IAsyncResult result)
at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)
I'm not sure what's causing this but I think it has something to do with the way I write the image to the database? (The array length is too big big, I don't really know how to change it)
Thank you for your help,
Thomas

looks like you need to change default reader quotas in binding, set lengths to appropriate values for you:
<readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="2147483646" maxBytesPerRead="4096" maxNameTableCharCount="5242880"/>

Related

Unable To Show Image In Picture Box Control From SQL Server Database In Windows Form Application

I want to add scanned images (Vehicle Documents) to SQL Server Database from my C# Windows Form Application. In the SQL Server database, the datatype for the column where scanned documents will be saved is Image where I want to store the image as an array for each scanned document. Here is my code that saves the data into the SQL Server database.
Browse Button Code:
private void btnBrowseFiles_Click(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Filter = "image files|*.jpg;*.png;*.gif;*.icon;*.bmp;*.*";
DialogResult dResult = fileDialog.ShowDialog();
if (dResult == DialogResult.OK)
{
pBoxVehicleDocument.Image = Image.FromFile(fileDialog.FileName);
}
}
Add Button Code:
private void btnAdd_Click(object sender, EventArgs e)
{
string documentName, vehicleId;
documentName = txtDocumentName.Text;
vehicleId = lblVehicleId.Text;
MemoryStream mStream = new MemoryStream();
pBoxDocument.Image.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
mStream.ToArray();
//The documentName, vehicleId and imageArray to be passed to AddVehicleDocuments Method within Vehicles Class.
//No I am getting invalid arguments exception on AddVehicleDocuments() method.
Vehicles.AddVehicleDocuments(documentName, vehicleId, imageArray);
}
And Finally the AddVehicleDocuments Method Code within Vehicles Class:
public static void AddVehicleDocuments(string documentName, int vehicleId, byte[] imageString)
{
string query = string.Format("insert into tblDocuments values ('{0}', {1}, {3})", documentName, vehicleId, imageString);
DataAccess.Execute(query);
}
Now, the following code is for image selection. I am not sure how can I convert the array values from the database back to a Picture Box on the Windows Form:
private void childDocumentDetails_Load(object sender, EventArgs e)
{
int documentId = Convert.ToInt32(lblDocumentId.Text);
DataRow dr = Vehicles.GetDocumentDetailsById(documentId);
txtDocumentName.Text = dr["DocumentName"].ToString();
txtVehicleNo.Text = dr["VehicleNo"].ToString();
//here the image array from the database will locate in dr["VehicleDocument"];
pBoxDocument.Image = //Need to write my code here
}
The DataRow dr contains all of the three records for the given document i.e. DocumentName, VehicleNo/VehicleID, and the byte string but the Picture Box Control still do not show the target image. Just need some expert suggestion in this regard.
Any help will be highly appreciated.
Because I was sure as per my research, that the Image data type on SQL Server-Side will work for me to store scanned documents for a vehicle. However, I modified my code later and used Verbinary(MAX) as the data type for storing images in the database.
I modified my insertion code which now looks like this:
private void btnAdd_Click(object sender, EventArgs e)
{
string documentName, vehicleId;
documentName = txtDocumentName.Text;
vehicleId = lblVehicleId.Text;
MemoryStream mStream = new MemoryStream();
pBoxDocument.Image.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] imagesBytes = mStream.ToArray();
Vehicles.AddVehicleDocuments(documentName, vehicleId, imagesBytes);
}
And the image selection code looks like:
private void childDocumentDetails_Load(object sender, EventArgs e)
{
int documentId = Convert.ToInt32(lblDocumentId.Text);
DataRow dr = Vehicles.GetDocumentDetailsById(documentId);
txtDocumentName.Text = dr["DocumentName"].ToString();
txtVehicleNo.Text = dr["VehicleNo"].ToString();
byte[] imageString = (byte[]dr["VehicleDocument"]);
MemoryStream mStream = new MemoryStream(imageString);
pBoxDocument.Image = Image.FromStream(mStream);
}
Thanks to #Jimi for suggesting code modifications.

NHibernate 2nd level cache with Prevalence

I'm writing a Windows Forms application which needs to store some NHibernate's entities data in a persistent 2nd layer cache. As far as I know, the only 2nd level cache provider which satisfies my app's requirements is Prevalence, but I'm getting an awkward exception when I configure it:
System.ArgumentNullException was unhandled
Message=Value cannot be null.
Parameter name: key
Source=mscorlib
ParamName=key
StackTrace:
at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
at NHibernate.Impl.SessionFactoryObjectFactory.GetNamedInstance(String name)
at NHibernate.Impl.SessionFactoryImpl.GetRealObject(StreamingContext context)
at System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at Bamboo.Prevalence.Implementation.PendingCommandsEnumerator.NextCommand()
at Bamboo.Prevalence.Implementation.PendingCommandsEnumerator.MoveNext()
at Bamboo.Prevalence.PrevalenceEngine.RecoverCommands(CommandLogReader reader, ExceptionDuringRecoveryHandler handler)
at Bamboo.Prevalence.PrevalenceEngine.RecoverSystem(Type systemType, CommandLogReader reader, ExceptionDuringRecoveryHandler handler)
at Bamboo.Prevalence.PrevalenceEngine..ctor(Type systemType, String prevalenceBase, BinaryFormatter formatter, ExceptionDuringRecoveryHandler handler)
at Bamboo.Prevalence.TransparentPrevalenceEngine..ctor(Type systemType, String prevalenceBase, BinaryFormatter formatter, ExceptionDuringRecoveryHandler handler)
at Bamboo.Prevalence.TransparentPrevalenceEngine..ctor(Type systemType, String prevalenceBase, BinaryFormatter formatter)
at Bamboo.Prevalence.PrevalenceActivator.CreateTransparentEngine(Type systemType, String prevalenceBase, BinaryFormatter formatter)
at Bamboo.Prevalence.PrevalenceActivator.CreateTransparentEngine(Type systemType, String prevalenceBase)
at NHibernate.Caches.Prevalence.PrevalenceCacheProvider.SetupEngine()
at NHibernate.Caches.Prevalence.PrevalenceCacheProvider.Start(IDictionary`2 properties)
at NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
at NHibernate.Cfg.Configuration.BuildSessionFactory()
at AcessoDados.DB.Configure() in C:\Users\Herberth\MyProject\DataAccess\DB.cs:line 78
This is only extra code I'm using:
configuration.SessionFactory().Caching.Through<NHibernate.Caches.Prevalence.PrevalenceCacheProvider>().PrefixingRegionsWith("MyRegion").WithDefaultExpiration(60);
It works fine when I comment out this line (without the cache, of course);
Here's the complete code I'm using:
configuration = new Configuration();
var mapper = new ModelMapper();
mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
HbmMapping domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
configuration.DataBaseIntegration(c =>
{
c.Dialect<MySQLDialect>();
c.ConnectionString = #"Server=localhost;Database=mydb;Uid=root;Pwd=mypwd";
c.ConnectionString = DBConnectionStrings.Principal;
c.LogFormattedSql = true;
c.LogSqlInConsole = true;
c.IsolationLevel = System.Data.IsolationLevel.ReadCommitted;
});
configuration.AddMapping(domainMapping);
configuration.Cache(c => { c.UseQueryCache = true; });
configuration.SessionFactory().Caching.Through<NHibernate.Caches.Prevalence.PrevalenceCacheProvider>().PrefixingRegionsWith("MyRegion").WithDefaultExpiration(60);
SessionFactory = configuration.BuildSessionFactory();
All dependencies are in their latest version.
Thanks in advance!
I had this issue because the directories NHibernate.Cache.StandardQueryCache and UpdateTimestampsCache in the executable directory got out of date.
However, that lead to the next issue -- I couldn't install under Program Files because NHibernate attempted to create these directories on first run.

Excel doc contents to webservice

I have a wpf staff creation window in which I can create basic information like first name, last name etc this creates the staff in my REST web service. An example:
Client side:
private void CreateStaffMember_Click(object sender, RoutedEventArgs e)
{
string uri = "http://localhost:8001/Service/Staff";
StringBuilder sb = new StringBuilder();
sb.Append("<Staff>");
sb.AppendLine("<FirstName>" + this.textBox1.Text + "</FirstName>");
sb.AppendLine("<LastName>" + this.textBox2.Text + "</LastName>");
sb.AppendLine("<Password>" + this.passwordBox1.Password + "</Password>");
sb.AppendLine("</Staff>");
string NewStudent = sb.ToString();
byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "application/xml";
req.ContentLength = arr.Length;
Stream reqStrm = req.GetRequestStream();
reqStrm.Write(arr, 0, arr.Length);
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
MessageBox.Show("Staff Creation: Status " + resp.StatusDescription);
reqStrm.Close();
resp.Close();
}
Web Service side:
#region POST
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Staff")]
void AddStaff(Staff staff);
#endregion
public void AddStaff(Staff staff)
{
staff.StaffID = (++eCount).ToString();
staff.Salt = GenerateSalt();
byte[] passwordHash = Hash(staff.Password, staff.Salt);
staff.Password = Convert.ToBase64String(passwordHash);
staffmembers.Add(staff);
}
All fine on that side, but Im looking to "import" the staff details from an excel spreadsheet, not sure if import is the correct word but I want to take the first names and last names contained in such n such spreadsheet and add them to the web service from the client side wpf application.
How would I go about it? I have my open file dialog:
private void Import_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
}
}
So I open my excel spread sheet then how would I go about taking the inner contents and sending it to the web service? Really stuck on the code or how to go about it :/
Just looking for an automated way of adding staff members rather than manually typing the names, but seeing as the staff excel doc could be named anything I wanted the open file dialog box. The structure inside will always be the same first name then last name.
First, here is my test Excel file that contains the Staff you want to import:
(Column 'A' if first name, column 'B' is last name and column 'C' is the password...)
Ok, so assuming that your code calling your web service works, here is my version of the Import_Click method (and a generic method to save new staff):
private void Import_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
Microsoft.Office.Interop.Excel.Application vExcelObj = new Microsoft.Office.Interop.Excel.Application();
try
{
Workbook theWorkbook = vExcelObj.Workbooks.Open(filename, Type.Missing, true);
Worksheet sheet = theWorkbook.Worksheets[1]; // This is assuming that the list of staff is in the first worksheet
string vFirstName = "temp";
string vLastName = "temp";
string vPassword = "temp";
int vIndex = 1;
while (vFirstName != "")
{
// Change the letters of the appropriate columns here!
// In my example, 'A' is first name, 'B' is last name and 'C' is the password
vFirstName = sheet.get_Range("A" + vIndex.ToString()).Value.ToString();
vLastName = sheet.get_Range("B" + vIndex.ToString()).Value.ToString();
vPassword = sheet.get_Range("C" + vIndex.ToString()).Value.ToString();
this.SaveNewStaff(vFirstName, vLastName, vPassword);
vIndex++;
}
}
catch (Exception ex)
{
MessageBox.Show("Error processing excel file : " + ex.Message);
}
finally {
vExcelObj.Quit();
}
}
}
private void SaveNewStaff(string firstName, string lastName, string password) {
string uri = "http://localhost:8001/Service/Staff";
StringBuilder sb = new StringBuilder();
sb.Append("<Staff>");
sb.AppendLine("<FirstName>" + firstName + "</FirstName>");
sb.AppendLine("<LastName>" + lastName + "</LastName>");
sb.AppendLine("<Password>" + password + "</Password>");
sb.AppendLine("</Staff>");
string NewStudent = sb.ToString();
byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "application/xml";
req.ContentLength = arr.Length;
Stream reqStrm = req.GetRequestStream();
reqStrm.Write(arr, 0, arr.Length);
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
//MessageBox.Show("Staff Creation: Status " + resp.StatusDescription);
reqStrm.Close();
resp.Close();
}
Note: I have REMed out the MessageBox in the call to the web service to make sure you are not annoyed by it if the list is long, but you are free to "unREM" it if you need confirmation for every staff creation. In the same line of taught, there is not validation that the creation has occurred successfully. I would need more details to create a decent validation process.
Also VERY important, this does not validate if the staff you are saving already exists in the list. If you re-run this import procedure multiple times, it may (and probably will) create duplicate entries.
Cheers

Silverlight - How to get Webresponse string from WebClient.UploadStringAsync

public void Register(string email, string name, string hash)
{
string registerData = "{\"email\":\"" + email + "\",\"name\":\"" + name + "\",\"hash\":\"" + hash + "\"}";
WebClient webClient = new WebClient();
webClient.Headers["Content-Type"] = "application/json";
webClient.UploadStringCompleted += new UploadStringCompletedEventHandler(HandleRegisterAsyncResult);
webClient.UploadStringAsync(new Uri(registerUrl), registerData);
}
void HandleRegisterAsyncResult(object sender, UploadStringCompletedEventArgs e)
{
}
I'm basically trying to call a webservice with a https:// post command that takes a data string. It works well, except when I get an error I can't seem to find the actual WebResponse content. If I cast the e.Error that was returned to a WebException there's a class called Response that's a BrowserHttpWebResponse but the ContentLength is 0 (eventhough I can see the content lenght is not 0 in fiddler)
Is there a way to get the response content with this method? And if not is there another way to do a Post command that does allow me to get the response content?

WP7: can't get img from httpget url using webclient.OpenReadAsync

I need to get image from this API on Windows phone7 appplication,
getvmsimg
Description :
API for get variable message sign (VMS) as img
URL:
http://athena.traffy.in.th/apis/apitraffy.php?api=…&id=…[w=...]&[h=...]
Formats:
Image: PNG
HTTP Method:
GET
Requires Authentication :
true
API rate limited :
unlimited
and this is my code
I have to get a session key by another API first(Completely,No problem) and then i have to use the session key as a parameter in httpget url.
my key is correctly 100 percent, i have checked.
but It error at "image.SetSource(e.Result);" line (Unspecified error).
public intsign()
{
InitializeComponent();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("http://api.traffy.in.th/apis/getKey.php?appid="+appid));
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
rd = e.Result;
sessionkey = MD5Core.GetHashString(appid + rd) + MD5Core.GetHashString(hiddenkey + rd);
//MessageBox.Show(sessionkey);
client2.OpenReadCompleted += new OpenReadCompletedEventHandler(client2_OpenReadCompleted);
client2.OpenReadAsync(new Uri("http://athena.traffy.in.th/apis/apitraffy.php?api=getvmsimg&key=" + sessionkey + "&appid=" + appid + "&id=1&h=480&w=480"),client2);
}
void client2_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
BitmapImage image = new BitmapImage();
image.SetSource(e.Result);
intsignimg.Source = image;
}
thx, guy
Did you try to write the entire stream (with a buffer or else) into a MemoryStream and then use that MemoryStream instead of using directly the resulting stream ?

Resources