How to execute SQL query in a new database? - asp.net-mvc

My problem is like this... I'm creating a software where you have different areas of a business and those areas have a property name ConnectionString.
So when the administrator of the system wants to know certain specific information of the area all he does is register a SQL query.
My problem is in the logic of how to do execute the query. I'm creating a new DbContext and pass the connection string but I can't find a function of DbContext to run the query.
Does someone know any function of DbContext to run a query and get the result?

If you require to execute raw query in Entity Framework Core using DbContext object you can access like
For access raw query
var students = context.Students
.FromSql("SELECT * FROM dbo.Students Where id = 1")
.ToList();
If your requirement is access or get data from a stored procedure:
var students = context.Students
.FromSql("EXECUTE dbo.GetTopperStudents")
.ToList();
if passing with parameter then
var name = new SqlParameter("name", "abc");
var students = context.Students
.FromSql("EXECUTE dbo.GetTopperStudents #name",name )
.ToList();
if execute command insert/update/delete then
var commandText = "INSERT Students (name) VALUES (#name)";
var name = new SqlParameter("#name", "Test");
context.Database.ExecuteSqlCommand(commandText, name);
if you are execute query or stored procedure in not your model or you add custom model then you can execute as query like
my studentFees Model is not any model related to database.
public class StudentFees
{
public int StudentId { get; set; }
public string StudentName { get; set; }
public decimal Fees { get; set; }
public DateTime FeesDate { get; set; }
}
and just add your query into your DbContext OnModelCreating() method
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<StudentFees>();
}
now if you can access and execute your query or your stored procedure in custom model
var studentId = new System.Data.SqlClient.SqlParameter("#studentId", 1);
var studentsFees = _dbContext.Query<StudentFees>.FromSql("GetStudentFees #studentId", studentId).ToList();
in this way you can access or set your custom model also and execute query or stored procedure.
Let me know require more information.

Related

The entity or complex type cannot be constructed in a LINQ to Entities query - using lambda expression

I am trying this code I saw in a tutorial:
public ActionResult GetSearchRecord(string SearchText)
{
List<Unit_Of_Measurement> list = db.Unit_Of_Measurement.Where(x=>x.name.Contains(SearchText) && x.is_deleted == 0).Select(x => new Unit_Of_Measurement { name = x.name}).ToList();
return PartialView("SearchPartial", list );
}
This is the Unit_Of_Measurement model(I used db first approach when creating this):
public partial class Unit_Of_Measurement
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Unit_Of_Measurement()
{
this.Ingredients = new HashSet<Ingredient>();
}
public int id { get; set; }
public string name { get; set; }
public byte is_deleted { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Ingredient> Ingredients { get; set; }
}
But I am getting this error
The entity or complex type 'hwbModel.Unit_Of_Measurement' cannot be constructed in a LINQ to Entities query.
You cannot project into model type directly. Try using annonymous type or DTO, that is data transfer object.
Annonymous type
List<Unit_Of_Measurement> list = db.Unit_Of_Measurement.Where(x=>x.name.Contains(SearchText) && x.is_deleted == 0).Select(x => new { name = x.name}).ToList().Select(x => new Unit_Of_Measurement { name = x.name}).ToList();
Using DTO
Create new class for DTO.
public class UnitOfMeasurementDTO
{
public string Name { get; set; }
}
var list = db.Unit_Of_Measurement.Where(x=>x.name.Contains(SearchText) && x.is_deleted == 0).Select(x => new UnitOfMeasurementDTO { Name = x.name}).ToList();
Then you need to update your "PartialView" to support new DTO rather than Unit_Of_Measurement model.
Update
This is an Entity Framework (EF) restriction. LINQ to entities will convert your LINQ query in to command tree query which will execute against EF in order to return objects.
Construct an ObjectQuery instance from ObjectContext.
Compose a LINQ to Entities query in C# or Visual Basic by using the
ObjectQuery instance.
Convert LINQ standard query operators and expressions to command
trees.
Execute the query, in command tree representation, against the data
source. Any exceptions thrown on the data source during execution are
passed directly up to the client.
Return query results back to the client.
There are some restrictions when building command trees which can be execute against EF, so that project into model type directly does not support EF. Which means nothing wrong in your LINQ query, but cannot execute against EF. Anonymous types are not tracked in EF and completely separate from your model, so that it will work without any issues. These restrictions may have introduced later versions of EF, you might have used old sample code.

Asp.net mvc call entity db data using Id for that particular row

Hi and thank you for taking your time to read. I am having trouble calling from a db using entity framework for a particular row. Here is my code for controller.
public ActionResult MyAccount(CurrentAccount ca, SaverAccount sa, int id)
{
var model = db.CurrentAccounts.FirstOrDefault(_ => _.Id == id);
Session["Id"] = ca.Id;
Session["CurrentAccountNumber"] = ca.CurrentAccountNumber;
Session["CurrentBalance"] = ca.CurrentBalance;
Session["SaverAccountNumber"] = sa.SaverAccountNumber;
Session["CurrentBalance"] = sa.SaverAccountNumber;
return View(model);
}
My model is a edmx entity file and i can seem to retrieve some data to my locals but only from 1 table and i need data to be from multiple tables selecting a full row of data for a paricular Id then having this information visable on the same view. There is also a relation between id on both tables. Thanks :)
Here you have called wrong object because you are fetching data in model variable but calling from ca. please use as following
public ActionResult MyAccount(CurrentAccount ca, SaverAccount sa, int id)
{
var model = db.CurrentAccounts.FirstOrDefault(_ => _.Id == id);
Session["Id"] = model.Id;
Session["CurrentAccountNumber"] = model.CurrentAccountNumber;
Session["CurrentBalance"] = model.CurrentBalance;
Session["SaverAccountNumber"] = sa.SaverAccountNumber;
Session["CurrentBalance"] = sa.SaverAccountNumber;
return View(model);
}
You need to execute join query to get data from two models like following exmaple
Create a common class like follwing
public class datafrombothclass
{
public int Id { get; set; }
public String saveaccount_name { get; set; }
public String currrentaccount_name { get; set; }
}
Now use join query in entity framework to get data from both model in you case from CurrentAccount and SaverAccount.
See the bellow code example:
var frombothclass=(from a in Model.saveaccount join s in Model.currentaccountaccount
where a.Id=id
select new datafrombothclass{
Id=a.Id,
saveaccount_name=s.name,
currrentaccount_name=a.name
});
return View(frombothclass);
Hope you will get the solution.

How to return value with E.F. IDbSet<T>

I have ASP.NET MVC 5 web project with E.F. 6.1.3.
I use IDbSet and its method Add to insert new data in my database. I also use context to save changes.
protected IDbSet<T> DbSet { get; set; }
public DbContext Context { get; set; }
private void Insert(T item)
{
this.DbSet.Add(item);
Context.SaveChanges();
}
When i insert new item in database
Is there any equivalent way in this interface to Sql Command.ExecuteScalar ?
In other words i need to get the Id of newly inserted item (my Id is first column and first row in current table).
You dont need ExecuteScalar (but you have to create your POCOs thru context.Set<T>().Create() method no, you dont have to, it works without proxy)
class MyPoco
{
[Key]
public int Id {get;set;}
}
...
var myPoco = context.Set<MyPoco>().Add(context.Set<MyPoco>().Create());
context.SaveChanges();
int newId = myPoco.Id;
However, if you have to have some direct store query, you can use context.ExecuteStoreQuery (its not on IDbSet, but on Context class)
var departments = context.ExecuteStoreQuery<string>
("select Name from Department where DepartmentID < #p0", 5);
EDIT (after you added code :) ):
You can add custom interface (or even base class) to your POCO with Id property:
public interface IId
{
int Id {get;}
}
class MyPoco
: IId
{
[Key]
public int Id {get;set;}
}
and update your Insert code like this:
private int Insert(T item)
where T : IId
{
this.DbSet.Add(item);
Context.SaveChanges();
return item.Id;
}
Note this doesnt work when you create your POCO simply by poco = new Poco() - this way, you give up lot of EF functionality (proxies), you have to use IDbSet<T>.Create() method) It work.
Or keep your item and take Id value after you send it to your Insert(item):
var myPoco = context.Set<MyPoco>().Add(context.Set<MyPoco>().Create());
context.Insert(myPoco);
int newId = myPoco.Id;

EF select to POCO from "complex" object won't compile

This is my method that is giving the error.
public List<StatusViewModel> GetStatuses(){
using(var ctx = new AppStatusEntities()){
var result = ctx.GetLatestStatuses().Select(r => new StatusViewModel
{
r.ApplicationId,
r.ApplicationName,
r.ApplicationStatus,
r.LastRun
}).ToList();
return result;
}
}
StatusViewModel is a POCO.
public class StatusViewModel{
public Guid ApplicationId {get;set;}
public string ApplicationName {get;set;}
public string ApplicationStatus {get;set;}
public DateTime LastRun {get;set;}
}
The error message is
Cannot initialize type 'StatusViewModel' with a collection initializer because it does not implement 'System.Collections.IEnumerable'
I can only assume it has something to do with the return type of the stored procedure call being a "complex" as specified when I imported the function in the Entity Data Model. But I cannot figure out why that would matter. If I do something like ctx.ApplicationStatus.Select(r => new StatusViewModel {... where ApplicationStatus is a table and not a stored procedure call, then that code will compile without errors.
Try it this way:
var result = ctx.GetLatestStatuses().Select(r => new StatusViewModel
{
ApplicationId = r.ApplicationId,
ApplicationName = r.ApplicationName,
ApplicationStatus = r.ApplicationStatus,
LastRun = r.LastRun
}).ToList();
The difference between your stored procedure call and direct access to ObjectSet is Linq implementation. Your first example with stored procedure uses projection your application using Linq-to-Objects whereas the second example uses projection in SQL using Linq-to-entities.

Stored Procedure Multiple-Table Output With LINQ and ASP.NET MVC

Quite often our systems call stored procedures which output multiple tables worth of results. Previously we used XML outputs to get each table and relate them correctly using XSLT. If I were using ASP.NET MVC with LINQ calling a stored procedure, how do I get each of the tables and then output the data as necessary?
this article here explains everything. This is the same article which i linked, in your previous SO question.
There's an article here about LINQ to SQL and stored procedures, especially the section 'Handling Multiple Result Shapes from SPROCs':
LINQ to SQL - Retrieving Data Using Stored Procedures.
Is that useful in your case?
Otherwise, not using LINQ to SQL, maybe use SqlDataReader's NextResult to go through the results, for example:
IList<Employee> employees = new List<Employee>();
IList<Customer> customers = new List<Customer>();
using (SqlConnection connection = new SqlConnection
(Properties.Settings.Default.NorthwindConnectionString))
using (SqlCommand command = new SqlCommand
("GetEmployeesAndCustomers", connection))
{
command.CommandType = CommandType.StoredProcedure;
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Employee e = new Employee{EmployeeID = (int)reader["EmployeeID"]};
employees.Add(e);
}
reader.NextResult();
while (reader.Read())
{
Customer c = new Customer{CustomerID = (string)reader["CustomerID"]};
customers.Add(c);
}
}
}
Edit: Example of how to handle custom data combinations that are not easily fit into domain model objects; in this case retrieving orders along with the customers for the orders:
namespace Company.Application.ViewModel
{
public class CustomerOrder
{
public string CustomerID { get; set; }
public string CustomerName { get; set; }
public int OrderID { get; set; }
public DateTime? OrderDate { get; set; }
}
}
namespace Company.Application.Repository
{
public class CustomerOrderRepository
{
public IList<CustomerOrder> GetCustomerOrders()
{
NorthwindDataContext db = new NorthwindDataContext();
var custorders = from customer in db.Customers
join order in db.Orders
on customer.CustomerID equals order.CustomerID
select new CustomerOrder
{
CustomerID = customer.CustomerID,
CustomerName = customer.CompanyName,
OrderID = order.OrderID,
OrderDate = order.OrderDate
};
return custorders.ToList();
}
}
}
Inspiration for this: In the chapter about NerdDinner, Scott Guthrie talks about creating custom 'ViewModel' objects to hold data from for example joins that are not easily fit into the domain model objects.

Resources