Inserting value from API to database - c#

I created a ConsoleApplication that gets information from an API and then is supposed to put one of the values in a table from the database. Everything works fine (like getting the values and filling the object data with them) but I can't seem to figure out a way to push it to the database.
class Program
{
static void Main(string[] args)
{
HttpClient cons = new HttpClient();
cons.BaseAddress = new Uri("APPURL");
cons.DefaultRequestHeaders.Accept.Clear();
cons.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
MyAPIGet(cons).Wait();
}
static async Task MyAPIGet(HttpClient cons)
{
using (cons)
{
HttpResponseMessage res = await cons.GetAsync("");
res.EnsureSuccessStatusCode();
if (res.IsSuccessStatusCode)
{
VirtualProduct virtualProduct = await res.Content.ReadAsAsync<VirtualProduct>();
Console.WriteLine("\n");
Console.WriteLine("---------------------Calling Get Operation------------------------");
Console.WriteLine("\n");
Console.WriteLine("Id Name ");
Console.WriteLine("-----------------------------------------------------------");
Console.WriteLine("{0}\t{1}\t", virtualProduct.Id, virtualProduct.Header);
Console.ReadLine();
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnectionString"].ConnectionString))
{
string insertQuery = #"UPDATE VirtualProduct SET ProductImageId = #Id WHERE Name='#Header';";
var result = db.Execute(insertQuery, virtualProduct);
}
}
}
}
}
After running this, everything works fine but my database does not get updated. Upon debugging, I discovered that using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnectionString"].ConnectionString)) has the following error:
ServerVersion = '((System.Data.SqlClient.SqlConnection)db).ServerVersion' threw an exception of type 'System.InvalidOperationException'
The connection string is perfectly fine, I double checked the app.config which looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add connectionString="Server= SERVER.database.windows.net;Database=SERVER_dev;User Id=user; Password=asd;" name="DefaultConnectionString" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>

As stated in this answer, try this:
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnectionString"].ConnectionString))
{
string insertQuery = #"UPDATE VirtualProduct SET ProductImageId = #Id WHERE Name='#Header';";
if (db.State==ConnectionState.Closed)
{
db.Open();
}
var result = db.Execute(insertQuery, virtualProduct);
}
After using using statement, everything declared inside using block of code gets disposed.

Related

Add Entity Framework Model to Class Library

I have created a class library and added a EF Model but as soon as I declare a variable my project just skip the rest of my code without any error. I do not understand what is causing this to happen.
Library Code
public class Phisc
{
//Global DB Entity variable
live_restoreEntities db = new live_restoreEntities();
//Write data to file
public void PhiscFile(int value)
{
string strFileName, strFilePath;
StreamWriter stm;
//Create a file name that will be created
strFileName = DateTime.Now.ToString("yyyyMMddHHmmss") + "_PHISC";
//The path that were the file will be saved
strFilePath = "c:\\" + strFileName + ".txt";
//Validate if file exists
if (!System.IO.File.Exists(strFilePath))
System.IO.File.Create(strFilePath).Dispose();
stm = new StreamWriter(strFilePath, false);
stm.Write("This is a test message from C#");
stm.Close();
}
}
WinForm Code
private void Form1_Load(object sender, EventArgs e)
{
Phisc.Phisc pFile = new Phisc.Phisc();
pFile.PhiscFile(14);
}
When I create a instance of the library it does not hit my PhiscFile Method.
I have added a breakpoint to it and it stops at this constructor
public live_restoreEntities() : base("name=live_restoreEntities", "live_restoreEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
I am using a windows application to test my library
The parameterless constructor goes out and look for the conenctionstring in the App.config file. It look next to the .exe file.
I'm guessing that you need to include your App.config (from your entity library) to your WinForms library.
In the App.config, it should look like this:
<configuration>
<connectionStrings>
<add name="live_restoreEntities"
connectionString="<your connection string here>"
providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>

How can I get a connection string from a text file?

I have developed a Windows application with the backend of SQL Server to insert employee names. I am going to insert the employee details on three databases one by one. So, I like to get connecting values from text file. Whenever I want to change the connection, I just want to enter the login details in the text file.
How can I get a connection string from a text file?
Use an app.config (MSDN) file.
Allows you to configure multiple named connection strings which you can access via the System.Configuration.ConfigurationManager class' ConnectionStrings property
Plaese try like this
using System;
using System.IO;
class Test
{
public static void Main()
{
string txtpath = #"c:\textfile.txt";
try
{
if (File.Exists(txtpath))
{
using (StreamReader sr = new StreamReader(txtpath))
{
while (sr.Peek() >= 0)
{
string ss = sr.ReadLine();
string [] txtsplit = ss.Split(';');
//now loop through array
string server=txtsplit[0].Tostring();
string userid= split[1].Tostring(); // user id
string password= split[2].Tostring(); // password
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.ToString());
}
}
}
You don’t need to use plain text file to do this. There is a special configuration file you can use and a set of classes to make your life easier.
Add configuration file to you project
Go to Add new item in the solution and select Application Configuration File
Add connection strings to the configuration file
Just copy / paste this and modify connection string and connection string name as needed
<configuration>
<connectionStrings>
<add name="Conn1" connectionString="Data Source=SERVER_NAME;Initial Catalog=DATABASE;Persist Security Info=True;User ID=USER;Password=12345678" providerName="System.Data.SqlClient"/>
<add name="Conn2" connectionString="Data Source=SERVER_NAME;Initial Catalog=DATABASE;Persist Security Info=True;User ID=USER;Password=12345678" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
Add System.Configuration reference to your project
Right click references, go to add new and select System.Configuration from .NET tab
Add wrapper class
This is not needed but it will make your life easier. Create a class like this so you don’t have to call configuration manager every time you need to connect to database
using System;
using System.Configuration;
using System.Text;
namespace WindowsFormsApplication4
{
class Config
{
public static string CONNECTION_STRING_1
{
get
{
return ConfigurationManager.ConnectionStrings["Conn1"].ConnectionString;
}
}
public static string CONNECTION_STRING_2
{
get
{
return ConfigurationManager.ConnectionStrings["Conn2"].ConnectionString;
}
}
}
}
Use connection strings in other methods like this
SqlConnection conn = new SqlConnection(Config.CONNECTION_STRING_1);
class Sql
{
public static string ReadCS()
{
using (var streamReader = File.OpenText("SqlSettings.txt"))//Enter FileName
{
var lines = streamReader.ReadToEnd();
return lines;
}
}
public SqlConnection con = new SqlConnection(Sql.ReadCS());
}

Deployable database Test Methods

I am currently in the middle of creating an app that uses a sql CE database, I have made this database deploy-able with the application, however the problem I'm having at the moment is I need to run TestMethods but this is erroring out when it doesn't find the database as its looking in the "testingProject" folder under debug or release as that is it's Data Directory
using (SqlCeConnection sqlCon = new SqlCeConnection(#"Data Source=|DataDirectory|\database.sdf;Persist Security Info=False;"))
The code above is my connection string, so I'm guessing that means that the test is running and searching for a database in its own data directory
Any help on what I could do without changing the database connection string, database location and still leaving my application deployable? or am I asking something impossible?
EDIT
[TestMethod]
public void TestForReadingFromDB()
{
List<string> list = class.readDB();
Assert.IsNotNull(list);
Assert.AreNotEqual(0, list.Count);
}
just added in the test method that's currently failing
In the test project you can override the DataDirectory location using
AppDomain.CurrentDomain.SetData("DataDirectory", <PATH_TO_DATA_DIRECTORY>);
For instance in my app.config file the testing projects I have
<appSettings>
<add key="DataDirectory" value="..\..\Database"/>
</appSettings>
In my test fixture base I have:
var dataDirectory = ConfigurationManager.AppSettings["DataDirectory"];
var absoluteDataDirectory = Path.GetFullPath(dataDirectory);
AppDomain.CurrentDomain.SetData("DataDirectory", absoluteDataDirectory);
This sets the DataDirectory to the folder /Database under the test project folder structure.
Once I drop or create a copy of the database in there I can easily run Integration Tests.
this is how I specify the data directory path for testing in my initialize data class
public class TestClasse
{
public TestClass()
{
GetAppDataDirectoryForTesting();
}
private static string GetAppDataDirectoryForTesting()
{ //NOTE: must be using visual studio test tools for this to work
string path = AppDomain.CurrentDomain.BaseDirectory;
var dirs = path.Split(Path.DirectorySeparatorChar);
var appDataPath = "";
for (int i = 0; i < dirs.Length - 3; i++)
{
appDataPath += dirs[i] + Path.DirectorySeparatorChar.ToString();
}
appDataPath = appDataPath + "[foldername(i.e. in my case project name)]" + Path.DirectorySeparatorChar.ToString() + "App_Data";
return appDataPath;
}
[TestMethod]
public void SomeTestMethod()
{
....test code
}
}

Keyword not supported: 'name'

So I'm going through this tutorial that seems so simple but I can't seem to get it to work.
http://msdn.microsoft.com/en-us/data/gg685489
This is the error I'm receiving when running my app: "Keyword not supported: 'name'."
Now I've looked at other posts similar to mine and it seemed like the connection string was the issue. So I looked closely at but can't see any real differences.
<add name="BBCommercialSolutionsEntities"
connectionString="metadata=res://*/Models.BBCommercialSolutions.csdl|res://*/Models.BBCommercialSolutions.ssdl|res://*/Models.BBCommercialSolutions.msl;provider=System.Data.SqlClient;provider connection string="data source=MYSOURCENAME;initial catalog=MYDATABASENAME;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
In my CompanyController.cs class, I receive the error when using the .ToList().
public ActionResult Index()
{
//return View();
using (var db = new BBCommercialSolutionsEntities())
{
//return View(db.BBCSCompanies.ToList());
var tbl = db.BBCSCompanies;
var list = tbl.ToList();
return View(tbl.ToList());
}
}
And "new BBCommercialSolutionsEntities()" goes to my auto-generated template
public BBCommercialSolutionsEntities()
: base("name=BBCommercialSolutionsEntities")
{
}
Any ideas, thoughts, explanations, rants would help.
Just use BBCommercialSolutionsEntities
public BBCommercialSolutionsEntities() : base("BBCommercialSolutionsEntities")
{
}

How to get the values of a ConfigurationSection of type NameValueSectionHandler

I'm working with C#, Framework 3.5 (VS 2008).
I'm using the ConfigurationManager to load a config (not the default app.config file) into a Configuration object.
Using the Configuration class, I was able to get a ConfigurationSection, but I could not find a way to get the values of that section.
In the config, the ConfigurationSection is of type System.Configuration.NameValueSectionHandler.
For what it worth, when I used the method GetSection of the ConfigurationManager (works only when it was on my default app.config file), I received an object type, that I could cast into collection of pairs of key-value, and I just received the value like a Dictionary. I could not do such cast when I received ConfigurationSection class from the Configuration class however.
EDIT:
Example of the config file:
<configuration>
<configSections>
<section name="MyParams"
type="System.Configuration.NameValueSectionHandler" />
</configSections>
<MyParams>
<add key="FirstParam" value="One"/>
<add key="SecondParam" value="Two"/>
</MyParams>
</configuration>
Example of the way i was able to use it when it was on app.config (the "GetSection" method is for the default app.config only):
NameValueCollection myParamsCollection =
(NameValueCollection)ConfigurationManager.GetSection("MyParams");
Console.WriteLine(myParamsCollection["FirstParam"]);
Console.WriteLine(myParamsCollection["SecondParam"]);
Suffered from exact issue. Problem was because of NameValueSectionHandler in .config file. You should use AppSettingsSection instead:
<configuration>
<configSections>
<section name="DEV" type="System.Configuration.AppSettingsSection" />
<section name="TEST" type="System.Configuration.AppSettingsSection" />
</configSections>
<TEST>
<add key="key" value="value1" />
</TEST>
<DEV>
<add key="key" value="value2" />
</DEV>
</configuration>
then in C# code:
AppSettingsSection section = (AppSettingsSection)ConfigurationManager.GetSection("TEST");
btw NameValueSectionHandler is not supported any more in 2.0.
Here's a good post that shows how to do it.
If you want to read the values from a file other than the app.config, you need to load it into the ConfigurationManager.
Try this method: ConfigurationManager.OpenMappedExeConfiguration()
There's an example of how to use it in the MSDN article.
Try using an AppSettingsSection instead of a NameValueCollection. Something like this:
var section = (AppSettingsSection)config.GetSection(sectionName);
string results = section.Settings[key].Value;
Source:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d5079420-40cb-4255-9b3b-f9a41a1f7ad2/
The only way I can get this to work is to manually instantiate the section handler type, pass the raw XML to it, and cast the resulting object.
Seems pretty inefficient, but there you go.
I wrote an extension method to encapsulate this:
public static class ConfigurationSectionExtensions
{
public static T GetAs<T>(this ConfigurationSection section)
{
var sectionInformation = section.SectionInformation;
var sectionHandlerType = Type.GetType(sectionInformation.Type);
if (sectionHandlerType == null)
{
throw new InvalidOperationException(string.Format("Unable to find section handler type '{0}'.", sectionInformation.Type));
}
IConfigurationSectionHandler sectionHandler;
try
{
sectionHandler = (IConfigurationSectionHandler)Activator.CreateInstance(sectionHandlerType);
}
catch (InvalidCastException ex)
{
throw new InvalidOperationException(string.Format("Section handler type '{0}' does not implement IConfigurationSectionHandler.", sectionInformation.Type), ex);
}
var rawXml = sectionInformation.GetRawXml();
if (rawXml == null)
{
return default(T);
}
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(rawXml);
return (T)sectionHandler.Create(null, null, xmlDocument.DocumentElement);
}
}
The way you would call it in your example is:
var map = new ExeConfigurationFileMap
{
ExeConfigFilename = #"c:\\foo.config"
};
var configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var myParamsSection = configuration.GetSection("MyParams");
var myParamsCollection = myParamsSection.GetAs<NameValueCollection>();
This is an old question, but I use the following class to do the job. It's based on Scott Dorman's blog:
public class NameValueCollectionConfigurationSection : ConfigurationSection
{
private const string COLLECTION_PROP_NAME = "";
public IEnumerable<KeyValuePair<string, string>> GetNameValueItems()
{
foreach ( string key in this.ConfigurationCollection.AllKeys )
{
NameValueConfigurationElement confElement = this.ConfigurationCollection[key];
yield return new KeyValuePair<string, string>
(confElement.Name, confElement.Value);
}
}
[ConfigurationProperty(COLLECTION_PROP_NAME, IsDefaultCollection = true)]
protected NameValueConfigurationCollection ConfCollection
{
get
{
return (NameValueConfigurationCollection) base[COLLECTION_PROP_NAME];
}
}
The usage is straightforward:
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
NameValueCollectionConfigurationSection config =
(NameValueCollectionConfigurationSection) configuration.GetSection("MyParams");
NameValueCollection myParamsCollection = new NameValueCollection();
config.GetNameValueItems().ToList().ForEach(kvp => myParamsCollection.Add(kvp));
Here are some examples from this blog mentioned earlier:
<configuration>
<Database>
<add key="ConnectionString" value="data source=.;initial catalog=NorthWind;integrated security=SSPI"/>
</Database>
</configuration>
get values:
NameValueCollection db = (NameValueCollection)ConfigurationSettings.GetConfig("Database");
labelConnection2.Text = db["ConnectionString"];
-
Another example:
<Locations
ImportDirectory="C:\Import\Inbox"
ProcessedDirectory ="C:\Import\Processed"
RejectedDirectory ="C:\Import\Rejected"
/>
get value:
Hashtable loc = (Hashtable)ConfigurationSettings.GetConfig("Locations");
labelImport2.Text = loc["ImportDirectory"].ToString();
labelProcessed2.Text = loc["ProcessedDirectory"].ToString();
Try this;
Credit: https://www.limilabs.com/blog/read-system-net-mailsettings-smtp-settings-web-config
SmtpSection section = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");
string from = section.From;
string host = section.Network.Host;
int port = section.Network.Port;
bool enableSsl = section.Network.EnableSsl;
string user = section.Network.UserName;
string password = section.Network.Password;
This works like a charm
dynamic configSection = ConfigurationManager.GetSection("MyParams");
var theValue = configSection["FirstParam"];

Categories

Resources