REST API with dotnet core - c#

Thanks for your observations, i did applied them with the following code but after testing api returns no data. I have even used my connection string instead of dbcontext still nothing! I get this error Invalid attempt to call FieldCount when reader is closed and my reader is open. i am in this situation for a week now any help. The FromSql query just returns entities of a single table. my Store procedure takes a parameter and has joins with 4 tables. i have tried with "ExecuteSqlCommand" query as results is a -1 i get.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ActivaMobileAgent.Persistence;
using Microsoft.EntityFrameworkCore;
using ActivaMobileAgent.Model;
using System.Linq;
using System.Collections.Generic;
using System.Data.SqlClient;
using System;
using Dapper;
using System.Data;
using System.Data.Common;
namespace ActivaMobileAgent.Controllers
{
[Route("/api/Policy")]
public class PolicyController : Controller
{
private readonly ActivaMobileAgentDbContext context;
public PolicyController(ActivaMobileAgentDbContext context) => this.context = context;
public readonly string connectionString = "Data Source=Localhost;Initial Catalog=HELLOxx;User=sa; Password=Helloxx";
[HttpGet("{id}")]
public async Task<IActionResult> GetPolicy(string id)
{
using (var connection = new SqlConnection("Data Source=Localhost;Initial Catalog=Helios;User=sa; Password=P#ssw0rd"))
{
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText ="dbo.sproc_Contract_Get";
command.Parameters.Add(new SqlParameter("#ContractNumber", SqlDbType.VarChar) { Value = id });
connection.Open();
using (var result = await command.ExecuteReaderAsync())
{
return Json(result);
}
}
}
}
}

Your web-method doesn't return any data.
Instead of having a method that returns nothing, modify the method signature to
public async Task<IActionResult> GetPolicy( int id )
Once you've done that, the compiler will expect that this method returns some data.
I suppose that the stored proc returns some data, so you'll have to put it somewhere. Afterwards you can return the values using
return Ok(thedata);
Check the Ok method for instance.
If something went wrong, you shouldn't return Ok offcourse, but another Http status code that indicates what went wrong.
This leads me to saying that the functions in a REST service should always return the correct HTTP status code. Therefore, all your REST methods should return IActionResult or Task, and not only the data that is retrieved
Edit after the Question has been edited
The ExecuteReader() method returns a class that implements IDataReader. It's obviously not correct to return the datareader to the consumer of your webservice.
Instead, you'll have to use the IDataReader to read the data and use that data to populate some kind of model that you can use to return to the consumer of your service.
List<SomeClass> result = new List<SomeClass>();
using (var reader = await command.ExecuteReaderAsync())
{
while( reader.Read() )
{
result.Add(new SomeClass(dr.GetInt32(0), dr.GetString(1));
}
}
return Ok(result);
Next to that, I advise you to not format the data yourself to json or xml or whatever. Let ASP.NET handle that for you. ASP.NET will serialize the results to the appropriate format based on the value accept-header of the request that it has received.

ExecuteReaderAsync returns Task<SqlDataReader>. This is probably not a useful type to serialize as a JSON result. It represents a cursor over a dataset, not the data itself; the data hasn't actually been brought back from the database yet. As this blog article explains, there isn't a built-in way to turn a SqlDataReader into JSON. There are a couple of ways mentioned there, but the take-away is that you will have to write code that iterates the SqlDataReader and constructs results from it.
Typically to make this job easier you'd use an Object-Relational Mapper to do this work for you, an example is Dapper which has support for stored procedures (disclaimer: I#ve never used Dapper). Entity Framework is the usual for .net applications as it's built by Microsoft, but it's quite heavy and can be complex to use.
edit: Oh - I didn't spot that you had an Entity Framework DbContext already. That should allow you to execute the stored procedure and map it to a result natively.

Related

How to write Unit test for DAL which call stored procedure and direct SQL commands

I am writing unit test cases for DAL methods (which are calling stored procedures and some direct SQL commands and not returning methods). How can I mock the results coming from db in unit tests?
Please let me know sample references or suggestions. Please find the below sample code
public class Notification : Base, INotificationBal
{
public void InsertNotification(NotificationType notif)
{
using (var con = GetConnction())
{
using (var command = CreatSqlCommand(con, "sp_InsertNotifDetails"))
{
// notif.NotificationType=1, notif.NotificationName="Mobile"
command.SetParamsValues(
("#NotificationType", notif.NotificationType),
("#NotificationName", notif.NotificationName)
));
command.ExecuteNonQuery());
}
}
}
}
Thanks,
Sam
I am not aware of this.

Unity SQLite local database

I am making a small game in Unity and I'm in need of a database. I tried using SQLite database because that seemed to be recommended by the web.
Now I'm having troubles with actually connecting to the local database via c#.
I implemented the Data in SQLite .dll's.
I am trying to get 1 name from the database that I created using SQLite developer.
Below is my DataConnection class, which I use to connect to the database.
using UnityEngine;
using System.Collections;
using System.Data;
using Mono.Data.SqliteClient;
public class Dataconnection : MonoBehaviour {
private string _constr = #"Data Source=C:\Program Files (x86)\SharpPlus\SqliteDev\GameDatabase.db;Version=3;";
private IDbConnection _dbc;
private IDbCommand _dbcm;
private IDataReader _dbr;
public Dataconnection()
{
}
public Dataconnection(string constring)
{
_constr = constring;
}
public string ExcecuteQuery(string SQL)
{
string output = "";
try
{
_dbc = new SqliteConnection(_constr);
_dbc.Open();
_dbcm = _dbc.CreateCommand();
_dbcm.CommandText = SQL;
_dbr = _dbcm.ExecuteReader();
}
catch
{
}
while (_dbr.Read())
{
output = _dbr.GetString(0);
}
_dbc.Close();
return output;
}
}
Then I call the following method from another class:
datacon.ExcecuteQuery("SELECT name FROM employee WHERE empid = 1;");
I get the following errors when running the code:
So I'm guessing it has something to do with a 32/64 -bit mismatch or is there something wrong with creating an instance of a script like this?:
private Dataconnection datacon;
void Start()
{
datacon = new Dataconnection();
}
Happy to receive any help at all. I'm familiar with using database, just new to SQLite.
It says it cannot load the native sqlite.dll because you have there 64 bit version and it needs 32 bit
Place this in your app folder https://www.sqlite.org/2015/sqlite-dll-win32-x86-3081001.zip
Please fill that empty catch on line 38 with a throw;
as there is an exception hidden there which is the true cause of the null reference.
You could also post your connection string so I could make this answer better.
I got it working now. The problem was my that one of the SQLite .dll's was still 32bit. I did this tutorial over again and searched google for the 64bit .dll files and now it's working.

What scope does a using statement have without curly braces

I inherited the following code:
using (var dataAccessConnection = da.GetConnection()) //no opening curly brace here
using (var command = new SqlCommand(sql, dataAccessConnection.Connection))
{
command.CommandType = CommandType.Text;
using (var sqlDataReader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (sqlDataReader.Read())
{
rueckgabe.Add(new Myclass
{
Uid = Guid.NewGuid(),
ImportVersionUid = versionUid,
MyProperty = Convert.ToInt32(sqlDataReader["MyProperty"])
});
}
}
command.Connection.Close();
dataAccessConnection.Connection.Close();
}
Looking at the code I expexted an opening curly brace after the using clause.
The code compiles and does what it is expected to do. The application behaves unpredictable. At some time it cant access the Database server.
Does this code make sense? Does dataAccessConnection have the rigth scope?
Beginning with C# 8.0, the using keyword can be used as an attribute in the variable declarations of disposable objects (Reference). The semantics is as you would expect -- the objects are auto-disposed at the end of the scope.
public class Disposable : IDisposable
{
string name;
public Disposable(string name)
{
this.name = name;
}
public void Dispose()
{
Console.WriteLine(name + " disposed");
}
public void Identify()
{
Console.WriteLine(name);
}
static void Main(string[] args)
{
using Disposable d1 = new Disposable("Using 1");
Disposable d2 = new Disposable("No Using 2");
using Disposable d3 = new Disposable("Using 3");
Disposable d4 = new Disposable("No Using 4");
d1.Identify();
d2.Identify();
d3.Identify();
d4.Identify();
}
}
Output
Using 1
No Using 2
Using 3
No Using 4
Using 3 disposed
Using 1 disposed
using statements without explicit curly braces apply only to the following statement.
using (Idisp1)
// use it
// it's disposed
Thus, when chained, they work the same way. The second using here acts as a single statement.
using (Idisp1)
using (Idisp2)
{
}
Commenter stakx suggested that formatting to make it clear how the compiler reads the using blocks. In reality, these would usually be formatted as the OP encountered:
using (Idisp1)
using (Idisp2)
{
}
That is equivalent to this:
using (Idisp1)
{
using (Idisp2)
{
}
}
Notice that the first at the top is always the last to dispose. Thus, in all previous examples, Idisp2.Dispose() is called before Idisp1.Dispose(). That isn't relevant in many cases where you would do something like this, but I believe you should always be aware of what your code will do and make the informed decision not to care.
An example of this is when reading a web page:
HttpWebRequest req = ...;
using (var resp = req.GetResponse())
using (var stream = resp.GetResponseStream())
using (var reader = new StreamReader(stream))
{
TextBox1.Text = reader.ReadToEnd(); // or whatever
}
We get the response, get the stream, get the reader, read the stream, dispose the reader, dispose the stream, and finally, dispose the response.
Note, as commenter Nikhil Agrawal pointed out, that this is a language feature regarding blocks that is not specific to the using keyword. For example, the same applies to if blocks:
if (condition)
// may or may not execute
// definitely will execute
Versus
if (condition1)
if (condition2)
// will execute if both are true
// definitely will execute
Although you should never, of course, use if statements this way as it's dreadful to read, but I thought it'd help you understand the using case. I'm personally very okay with chaining using blocks.
The C# language specification (Version 5) describes a using statement as:
using-statement:
using ( resource-acquisition ) embedded-statement
That is:
The using statement obtains one or more resources, executes a statement, and then disposes of the resource.
(My emphasis)
So, how then do we end up using it with curly braces? Because the definition of embedded-statement is:
embedded-statement:
block
empty-statement
expression-statement
selection-statement
iteration-statement
jump-statement
try-statement
checked-statement
unchecked-statement
lock-statement
using-statement
yield-statement
And:
The embedded-statement nonterminal is used for statements that appear within other statements
And finally, we discover that block is defined as:
A block permits multiple statements to be written in contexts where a single statement is allowed.
block:
{ statement-listopt }
So basically, curly braces can always be used to take a situation where a single statement is accepted and to instead have multiple statements.
It just so happens that, almost always, we do want to make use of more than one statement, and so the curly-braces tend to be seen as part of if, using, etc statements. Whereas, in fact, they're a separate part of the language.

Problems accessing tables through relationship in mysql and Entity Framework

I am using C# and the Entity Framework to access a MySQL database.
I am grabbing the results of a stored procedure, and trying to turn them into a list of objects, However whenever it comes to the part what references a table through a one to many relationship, it fails with the error
There is already an open DataReader associated with this Connection which must be closed first.
The code I am using is here:
using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CarHireCommon.DataObjects;
namespace CarHireServer
{
public class DatabaseHandler
{
protected static DatabaseHandler instance;
protected carhireEntities1 Entities;
public static DatabaseHandler GetInstance()
{
if (instance == null)
instance = new DatabaseHandler();
return instance;
}
public DatabaseHandler()
{
Entities = new carhireEntities1();
}
public List<AvailableAssets> GetAvailableAssets(DateTime startDate, DateTime endDate)
{
ObjectResult<asset> res = Entities.GetAvailableAssets(startDate, endDate);
List<AvailableAssets> list = new List<AvailableAssets>();
foreach(var assetRes in res)
{
AvailableAssets asset=new AvailableAssets();
asset.id = assetRes.id;
asset.Comment = assetRes.comments;
asset.Make = assetRes.make;
asset.Model = assetRes.model;
asset.Fuel = assetRes.fuel;
asset.LongTerm = assetRes.longterm;
// This is the line that errors:
asset.Category = assetRes.category.categoryname;
list.Add(asset);
}
return list;
}
}
}
I have allready told it which table the Stored Procedure returns, and the other variables access correctly.
I have also tried doing it the long way with:
var cat = from b in Entities.categories where b.id == assetRes.category_id select b;
asset.Category = cat.FirstOrDefault<category>().categoryname;
However the thing still exceptions with the exact same error.
I found C# Entity Framework: There is already an open DataReader associated with this Connection which must be closed first which will probably help you exactly with this question.
GL!

Why can't I read a db4o file created by a Java app in a C# app?

I have a db4o database that was generate by a Java app and I'm trying to read it using a C# app.
However, when running the following line of code:
IObjectContainer db = Db4oEmbedded.OpenFile(#"..\..\..\Databases\people.db4o");
I get the following error:
Unable to cast object of type
'Db4objects.Db4o.Reflect.Generic.GenericObject' to type
'Db4objects.Db4o.Ext.Db4oDatabase'.
Any ideas? I know there are person objects that contain personId fields (along with others) in the DB. I'm using db4o version 8. I'm not sure what version was used to generate the database.
The entire program is:
using System;
using System.Collections.Generic;
using System.Linq;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using MyCompany.Domain;
namespace MyCompany.Anonymizer
{
internal class Program
{
// Private methods.
private static IEmbeddedConfiguration ConfigureAlias()
{
IEmbeddedConfiguration configuration = Db4oEmbedded.NewConfiguration();
configuration.Common.AddAlias(new TypeAlias("com.theircompany.Person", "MyCompany.Domain.Person, MyCompany.Domain"));
configuration.Common.Add(new JavaSupport());
return configuration;
}
private static void Main(string[] args)
{
IObjectContainer db = Db4oEmbedded.OpenFile(#"..\..\..\Databases\people.db4o");
try
{
IList<Person> result = db.Query<Person>();
for (int i = 0; i < result.Count; i++)
{
Person person = result[i];
Console.WriteLine(string.Format("Person ID: {0}", person.personId));
}
}
finally
{
db.Close();
}
}
}
}
The most common scenario in which this exception is thrown is when db4o fails to resolve the type of a stored object.
In your case, db4o is failing to read one of its internal objects which makes me believe you have not passed the configuration to the OpenFile() method (surely, the code you have posted is not calling ConfigureAlias() method);
Keep in mind that as of version 8.0 no further improvement will be done regarding cross platform support (you can read more details here).

Categories

Resources