Multiple row insertion in asp.net core with dapper package - asp.net-core

I want to perform multiple row insertion in asp.net core where dapper package is used. Here I use a model class, controller and another class. The result stored in database is a datatable which is converted from a list. Here I use a stored procedure with type.
public class PlanDetailsInputModel
{
public int MembershipPlanDetailsId { get; set; }
public int MembershipPlanId { get; set; }
public int CreatedBy { get; set; }
public string Flag { get; set; }
public List<dtPlanFeatureListModel> dtPricePlanDetails { get; set; }
}
public class dtPlanFeatureListModel
{
public long PricePlanFeatureId { get; set; }
}
This is my model class. Help me create my controller and the function.

If you have an insert statement and a List of objects that match up with the fields of the insert statement you can do something like the following.
public void UpdateDB()
{
List<Entity> entities = null;
entities = GetData();
var sql = #"INSERT INTO TABLE_01 ( Id, FieldA, FieldB ) VALUES ( #id, #FieldA, #Fieldb )";
using (var conn = (IDbConnection) GetDatabaseConnection())
{
if (conn.State == System.Data.ConnectionState.Closed)
conn.Open();
using (var tx = conn.BeginTransaction())
{
//conn.Execute
conn.Execute(sql, entities, tx);
tx.Commit();
}
}
}
The code above will loop over all the rows in entities and perform the insert statements. If you leave out the transaction, then it will commit after each insert. But you include the transaction, it will commit after all the rows are inserted.
You can find more about it here
Although, your question doesn't say which class will be inserted. I don't think Dapper can handle your class PlanDetailsInputModel with the List inside it. You will have to flatten it to a DTO Class and use that DTO class in the Dapper command instead or use two dapper insert commands. One for PlanDetailsInputModel and another one for the List of dtPlanFeatureListModel.
HTH

Related

Insert an item using stored procedure

I´m new to ASP.NET, I want to know if someone can explain how Insert works using a stored procedure. I'm using Dapper.
I have a product model like this:
using Dapper.Contrib.Extensions;
using System;
namespace Dto.Entities.Products
{
[Table("Product.ProductDetail")]
public class ProductDetail
{
[Key]
public int ProductDetailId { get; set; }
public int ProductId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
Now can someone explain me how can I do an insert in controller using a stored procedure? Regards
The quickest way is to handle all the logic in the controller as you said:
[HttpPost]
public async Task<IHttpActionResult> Post([FromBody]ProductDetail payload)
{
using (var connection = new SqlConnection("<your_connectionstring>"))
{
var parameters = new
{
ProductId = payload.ProductId,
Name = payload.Name,
Description = payload.Description
};
await connection.ExecuteAsync("<your_insert_sp>", parameters, commandType: CommandType.StoredProcedure).ConfigureAwait(false);
}
return Ok();
}
This is not the recommended way to go though.
You should always use a dto class instead of your real data model as the type going in or leaving your controller.
Also the db logic should be moved outside of the controller, for example to a repository class. Or you can use Mediatr to move your logic away from your action and keep your controllers thin.

One-to-Many relationship with ORMLite

The only examples I can find addressing this sort of scenario are pretty old, and I'm wondering what the best way is to do this with the latest version of ORMLite...
Say I have two tables (simplified):
public class Patient
{
[Alias("PatientId")]
[Autoincrement]
public int Id { get; set; }
public string Name { get; set; }
}
public class Insurance
{
[Alias("InsuranceId")]
[Autoincrement]
public int Id { get; set; }
[ForeignKey(typeof("Patient"))]
public int PatientId { get; set; }
public string Policy { get; set; }
public string Level { get; set; }
}
Patients can have multiple Insurance policies at different "levels" (primary, secondary, etc). I understand the concept of blobbing the insurance information as a Dictionary type object and adding it directly to the [Patient] POCO like this:
public class Patient
{
public Patient() {
this.Insurances = new Dictionary<string, Insurance>(); // "string" would be the Level, could be set as an Enum...
}
[Alias("PatientId")]
[Autoincrement]
public int Id { get; set; }
public string Name { get; set; }
public Dictionary<string, Insurance> Insurances { get; set; }
}
public class Insurance
{
public string Policy { get; set; }
}
...but I need the insurance information to exist in the database as a separate table for use in reporting later.
I know I can join those tables in ORMLite, or create a joined View/Stored Proc in SQL to return the data, but it will obviously return multiple rows for the same Patient.
SELECT Pat.Name, Ins.Policy, Ins.Level
FROM Patient AS Pat JOIN
Insurance AS Ins ON Pat.PatientId = Ins.PatientId
(Result)
"Johnny","ABC123","Primary"
"Johnny","987CBA","Secondary"
How can I map that into a single JSON response object?
I'd like to be able to map a GET request to "/patients/1234" to return a JSON object like:
[{
"PatientId":"1234",
"Name":"Johnny",
"Insurances":[
{"Policy":"ABC123","Level":"Primary"},
{"Policy":"987CBA","Level":"Secondary"}
]
}]
I don't have a lot of hope in this being do-able in a single query. Can it be done in two (one on the Patient table, and a second on the Insurance table)? How would the results of each query be added to the same response object in this nested fashion?
Thanks a ton for any help on this!
Update - 4/29/14
Here's where I'm at...In the "Patient" POCO, I have added the following:
public class Patient
{
[Alias("PatientId")]
[Autoincrement]
public int Id { get; set; }
public string Name { get; set; }
[Ignore]
public List<Insurance> Insurances { get; set; } // ADDED
}
Then, when I want to return a patient with multiple Insurances, I do two queries:
var patientResult = dbConn.Select<Patient>("PatientId = " + request.PatientId);
List<Insurance> insurances = new List<Insurance>();
var insuranceResults = dbConn.Select<Insurance>("PatientId = " + patientResult[0].PatientId);
foreach (patientInsurance pi in insuranceResults)
{
insurances.Add(pi);
}
patientResult[0].Insurances = insurances;
patientResult[0].Message = "Success";
return patientResult;
This works! I get nice JSON with nested items for Insurances while maintaining separate related tables in the db.
What I don't like is that this object cannot be passed back and forth to the database. That is, I can't use the same nested object to automatically insert/update both the Patient and InsurancePolicy tables at the same time. If I remove the "[Ignore]" decorator, I get a field in the Patient table called "Insurances" of type varchar(max). No good, right?
I guess I'm going to need to write some additional code for my PUT/POST methods to extract the "Insurances" node from the JSON, iterate over it, and use each Insurance object to update the database? I'm just hoping I'm not re-inventing the wheel here or doing a ton more work than is necessary.
Comments would still be appreciated! Is Mythz on? :-) Thanks...
An alternate more succinct example:
public void Put(CreatePatient request)
{
var patient = new Patient
{
Name = request.Name,
Insurances = request.Insurances.Map(x =>
new Insurance { Policy = i.Policy, Level = i.Level })
};
db.Save<Patient>(patient, references:true);
}
References are here to save the day!
public class Patient
{
[Alias("PatientId")]
[Autoincrement]
public int Id { get; set; }
public string Name { get; set; }
[Reference]
public List<Insurance> Insurances { get; set; }
}
public class Insurance
{
[Alias("InsuranceId")]
[Autoincrement]
public int Id { get; set; }
[ForeignKey(typeof("Patient"))]
public int PatientId { get; set; }
public string Policy { get; set; }
public string Level { get; set; }
}
I can then take a JSON request with a nested "Insurance" array like this:
{
"Name":"Johnny",
"Insurances":[
{"Policy":"ABC123","Level":"Primary"},
{"Policy":"987CBA","Level":"Secondary"}
]
}
...to create a new record and save it like this:
public bool Put(CreatePatient request)
{
List<Insurance> insurances = new List<Insurance>();
foreach (Insurance i in request.Insurances)
{
insurances.Add(new Insurance
{
Policy = i.Policy,
Level = i.Level
});
}
var patient = new Patient
{
Name = request.Name,
Insurances = insurances
};
db.Save<Patient>(patient, references:true);
return true;
}
Bingo! I get the new Patient record, plus 2 new records in the Insurance table with correct foreign key references back to the PatientId that was just created. This is amazing!
First you should define a foreign collection in Patient class. (with get and set methods)
#ForeignCollectionField
private Collection<Insurance> insurances;
When you query for a patient, you can get its insurances by calling getInsurances method.
To convert all into a single json object with arrays inside you can use a json processor. I use Jackson (https://github.com/FasterXML/jackson) and it works very well. Below will give you json object as a string.
new ObjectMapper().writeValueAsString(patientObject);
To correctly map foreign fields you should define jackson references. In your patient class add a managed reference.
#ForeignCollectionField
#JsonManagedReference("InsurancePatient")
private Collection<Insurance> insurances;
In your insurance class add a back reference.
#JsonBackReference("InsurancePatient")
private Patient patient;
Update:
You can use Jackson to generate objects from json string then iterate and update/create database rows.
objectMapper.readValue(jsonString, Patient.class);

Nested LINQ IQueryable and WCF WebApi

I have a method like this that works as expected.
[WebGet]
public IQueryable<BuildJobModel> GetCustomers()
{
var context = new MyDataContext(); // ADO.NET Entity Data Model
var query = from c in context.Customers
select new CustomerModel {
Id = c.Id,
Name = c.Name
};
return query;
}
But when I try to create a more complex query like this, it doesn't work.
[WebGet]
public IQueryable<BuildJobModel> GetCustomers()
{
var context = new MyDataContext(); // ADO.NET Entity Data Model
var query = from c in context.Customers
select new CustomerModel {
CustomerId = c.CustomerId,
Name = c.Name,
Orders = from o in c.Orders
select new OrderModel {
OrderId = o.OrderId,
Details = o.Details
}
};
return query;
}
The Models look like this:
public class CustomerModel
{
public int CustomerId { get; set; }
public string Name { get; set; }
public IEnumerable<OrderModel> Orders { get; set; }
}
public class OrderModel
{
public int OrderId { get; set; }
public string Details { get; set; }
}
The Exception:
Cannot serialize member Proj.CustomerModel.Logs of type System.Collections.Generic.IEnumerable`1[[Proj.OrderModel, Proj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] because it is an interface.
My Goals:
I want to be able to expose an IQueryable interface.
I want to return nested data.
I want to use my own Models, not the ado.net entities
I want to hit the database with as few queries as possible (one would be best).
I would strongly recommend not exposing IQueryable as a return type of a WCF service.
WCF was designed to return data not queries
You lose control over the nature of the query: someone might potentially use this query in a way that is resource-intensive
Ideally, if you want to return collections use array or a generic list.
With respect to your list of goals:
Can you explain this? I don't see what IQueryable interface has to do with nested data.
You can still return arrays or lists of your models
You have better control over performance if you execute query locally and return results instead
Update: Have a look at WCF Data Services - that might be able to do what you want.
In case you're trying to return JSON: the build in JsonFormatter is not able to (de)serialize interfaces. You should try the JSON.NET Formatter from WebApiContrib.
I think you just need to use an array rather than IEnumerable, like so...
public class CustomerModel
{
public int CustomerId { get; set; }
public string Name { get; set; }
public OrderModel[] Orders { get; set; }
}
public class OrderModel
{
public int OrderId { get; set; }
public string Details { get; set; }
}
If you're serializing this to json/xml I suspect the built-in serializers don't know what to do with IEnumerable.

NHibernate - query specific columns and return distinct records?

I am new to NH.
I have a table in a legacy DB that looks like this:
Id,
CompanyId,
Description,
[LOADS of other columns here]
I would like to return a DISTINCT set of data using NHibernate, selecting only specific columns and using a WHERE statement. The SQL would looks something like this:
SELECT DISTINCT
[table_name].CompanyId,
[table_name].Description
FROM
[table_name]
WHERE
[table_name].CompanyId = 2
Having googled this I came up with:
ProjectionList projections = Projections.ProjectionList();
projections.Add(Projections.Property("CompanyId"), "CompanyId");
projections.Add(Projections.Property("Name"), "SomeName");
var companyDto = session.QueryOver<Company>()
.Where(x => x.CompanyId == 2)
.Select(projections)
.TransformUsing(Transformers.AliasToBean<CompanyDto>())
.List<CompanyDto>();
if (companyDto != null)
Console.WriteLine(string.Format("{0}, {1}", companyDto.CompanyId, companyDto.SomeName));
Where the DTO is:
public class CompanyDto
{
public int CompanyId { get; set; }
public string SomeName { get; set; }
}
And the entity is:
public class Company
{
public virtual int Id { get; private set; }
public virtual int CompanyId { get; set; }
public virtual string Name { get; set; }
}
This does not bring back disinct records. I know that normally I would have to use a different transform (DistinctRootEntity) but I cannot use two transforms. How can I combine all of the things I want, into a single call? It must be possible, its basic SQL ....
I need to:
not use HQL
not bring back all columns for the record
not bring back duplicate rows
there is a Projection for this
var projections = Projections.Distinct(Projections.ProjectionList()
.Add(Projections.Property("CompanyId").As("CompanyId"))
.Add(Projections.Property("Name").As("SomeName"));

How can I sort in (n)hibernate on a property of a child object?

I have an object from my domain model that has a child object. How can I use a criteria query to order based on a property of the child?
For example:
class FooType
{
public int Id { get; set; }
public string Name { get; set; }
public BarType Bar { get; set; }
}
class BarType
{
public int Id { get; set; }
public string Color { get; set; }
}
...
// WORKS GREAT
var orderedByName = _session.CreateCriteria<FooType>().AddOrder(Order.Asc("Name")).List();
// THROWS "could not resolve property: Bar.Color of: FooType"
var orderedByColor = _session.CreateCriteria<FooType>().AddOrder(Order.Asc("Bar.Color")).List();
What do I need to do to enable this scenario? I'm using NHibernate 2.1. Thanks!
You need to either add an alias or create a nested criteria for your child. Not sure how to do this in NHibernate, in Hibernate it's done via createCriteria() and createAlias() methods.
You would then use the alias as prefix in order by.
Update Hibernate code sample:
Criteria criteria = session.createCriteria(FooType.class);
criteria.createAlias("bar", "b");
criteria.addOrder(Order.asc("b.color"));
I imagine in NHibernate it would be quite similar, though with property/entity names uppercased. Here's an example from NHibernate documentation.