I have a ADMINCIDENTS class with, schema "ADM" and Table "Incidents":
[Table("ADM.INCIDENTS")]
public class ADMINCIDENTS
{
[Key]
public int INCNUM { get; set; }
}
When I query my database, the sql code generated is:
SELECT DISTINCT [inc].[INCNUM]
FROM [ADM.INCIDENTS] AS [inc]
Sql says that [ADM.INCIDENTS] is an invalid object.
How do I annotate my table so that the sql query generated adds the schema in the front in brackets with the table in brackets after, like this:
SELECT DISTINCT [inc].[INCNUM]
FROM [ADM].[INCIDENTS] AS [inc]
Try this
[Table("INCIDENTS", Schema="ADM")]
public class ADMINCIDENTS
{
[Key]
public int INCNUM { get; set; }
}
Take a look at this: http://www.entityframeworktutorial.net/code-first/table-dataannotations-attribute-in-code-first.aspx
Related
I've got a relatively basic model - Users and Tags. There is a fixed list of Tags. A User can have multiple Tags and a Tag can be used by multiple users.
I had gone with structure below and finding performance issues when returning results.
public class User
{
public string Id {get; set;}
public virtual List<UserTag> UserTags {get; set}
}
public class UserTag
{
public string UserId { get; set; }
public User User { get; set; }
public int TagId { get; set; }
public Tag Tag{ get; set; }
}
public class Tag
{
[Key]
public int TagId { get; set; }
public string Name { get; set; }
public virtual List<UserTag> UserTags { get; set; }
}
I have the following query which is takings a long time (several seconds):
var x = db.Users.Include(u => u.UserTags).ThenInclude(u => u.Trait).ToList<User>();
I have tried writing it as such, which has improved the time, however it is still taking too long:
db.UserTags.Load();
db.Tags.Load();
var x = db.Users.ToList<User>();
Is there any other way to speed this up? Running a query directly in SQL SMS is almost instant (e.g.
select * from Users u left outer join UserTags t on t.UserId = u.Id)
In terms of data rows, it is apx Tags: 100, UserTags:50,000, Users: 5,000
First you can check how EF translates your request to SQL Server - therefore use the "SQL Server Profiler"
Then you could use the genereated query to check if there might be an missing index which speeds up the query
You also can try to write a Join instead of ThenInclude and see how the query then behaves
best regards
Jimmy
What I'm trying to achieve is like this:
Fill up a form in view
Save data into table1 with columns:
Id|OperationNumber|Name|ContactNo
table1 Id is the primary key
Save data into table2 with columns:
ReferenceId|OperationNumber
ReferenceId is the primary key of datatype uniqueidentifier
"OperationNumber" column in both table is related. when data is saved in table1, OperationNumber will also save in table2 together with autogenerated ReferenceId (uniqueidentifier)
Retrieving process is:
input ReferenceId as search
Display all the details from table1 and table2 in result view
So that is my problem, how do i save and retrieve data in two tables?
Here's what I currently have:
Controller:
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(RefViewModel myViewModel)
{
db.Table1.Add(myViewModel.Ref);
db.SaveChanges();
return RedirectToAction("Index");
}
Model:
public class RefViewModel
{
public Table1 Ref { get; set; }
public string OperationNumber { get; set; }
public string Name { get; set; }
public string ContactNo { get; set; }
}
In the above code can save only in table1. so what to do in order for me to save two tables?
(oh and btw. as you may have noticed the "Bind(Include =" is nowhere, I have disabled it because I'm getting null values when saving into database. so, anyways. that's not the problem anymore here. just mentioning)
Database is SQL Server
Edit: as for retrieving data
SearchController:
public ActionResult Search(string searchString)
{
var myRef = (from x in db.Table1
where x.OperationNumber.Contains(searchString)
select x).FirstOrDefault();
return View(myRef);
}
That returns details when I input the operationnumber. So the problem is how to retrieve details from two tables when I input only referenceId?
You can easily do this by using stored procedures. Define two property classes to represent two tables and use inheritance as follows.
public class Tablel
{
public string ID { get; set; }
public string OperationNumber { get; set; }
public string Name { get; set; }
public string ContactNo { get; set; }
}
public class Table2 extend Table1
{
public string ReferenceID { get; set; }
public string OperationNumber { get; set; }
}
Now you can use stored procedures to save and retrieve data from database. Use join when you retrieve data from database and you can use two separate queries when save data to two tables.
From c# metadata of DbContext.SaveChanges():-
Returns:
// The number of objects written to the underlying database.
so basically you will do something like this:-
public ActionResult Create(RefViewModel myViewModel)
{
db.Table1.Add(myViewModel.Ref);
var t1 = db.SaveChanges();
Table2 t2 = new Table2
{
OperationNumber = t1.OperationNumber
};
db.Table2.Add(t2);
db.SaveChanges();
return RedirectToAction("Index");
}
when the SaveChanges is called, it returns all the objects saved to the database so when you call SaveChanges for the first time, it will return a Table1 object and with that Table1 object you will populate the OperationNumber property of Table2 and call SaveChanges again.
if your operationnumber is unique then use this query on store procedure, you can found data using ReferenceID
Select * from table1 t1
inner join table2 t2 on t1.OperationNumber = t2.OperationNumber
where t2.ReferenceID = #pReferenceID
I am using EF6 and SQL Server 2014.
I have something like the following simplified model:
public class Order
{
public int Id { get; set; }
public DateTime Created { get; set; }
public IEnumerable<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public int Id { get; set; }
public int OrderId { get; set; }
public Order Order { get; set; }
public string ItemName { get; set; }
public int OrderItemNumber { get; set; }
}
The Id properties are standard auto-increment primary keys.
The OrderItem.OrderItemNumber property uniquely identifies an OrderItem within the context of a given Order.
When a new OrderItem row is inserted it needs to be assigned the next OrderItemNumber for the parent Order, something like
SELECT COALESCE(MAX(OrderItemNumber),0) FROM dbo.OrderItems WHERE OrderId = 2
Is there a means using EF6/SQL Server to auto-assign the OrderItemNumber at the point a row is inserted?
Although this proved an interesting learning experience on EF support for triggers (see https://github.com/NickStrupat/EntityFramework.Triggers) I eventually decided to re-model.
In this case my question was a result of incorrect modelling. The OrderItemNumber property was redundant so I removed it; the sequence the OrderItems were created can be inferred from the Id value, and there was no real requirement to allow re-sequencing.
I'm looking for a way to map a row of the following table with the following object :
create table Foo (
Id BIGINT IDENTITY (1, 1) NOT NULL,
A int,
ACertainty float,
B string,
BCertainty float
....
)
public class FuzzyValue<T>{
public T Value { get; private set; }
public double Certainty { get; private set; }
}
class Foo {
public FuzzyValue<int> A { get; set;}
public FuzzyValue<string> B { get; set;}
...
}
Obviously, I can have dapper return a dynamic and do the mapping manually, but this manual tedious work kind of defeats the purpose of dapper, doesn't it?
Is there an easy way to have dapper do the mapping automatically?
I ended up writing a not so trivial mapper to do this.
If someone needs it, the source is here and there's a nuget package available here
I have this exert from a POCO class with many fields:
public class Call
{
public int Id { get; set; }
public string Customer { get; set; }
public int StatusId { get; set; }
public int UserAssignedToId { get; set; }
public string UserAssignedToName { get; set; }
}
However my stored procedure returns different names to the properties above (in this case the Id is before:
IdCall
IdStatus
IdUserAssignedTo
This is the code I am using to execute the stored procedure:
var call = conn.Query<Call>("CallSPName", new { IdCall = callId }, commandType: CommandType.StoredProcedure).First();
How can I specify a mapping to say I would like "IdStatus" from my stored procedure map to "StatusId" in my POCO class and "IdCall" to "CallId" etc?
I don't have access to change the stored procedures as they are controlled by DBAs and older legacy systems are using them which would break if the fields got changed in the stored procedure.
Any ideas/thoughts appreciated.
The closest thing which comes to my mind is to have private properties mapped to columns returned by the stored procedure and make the public properties with the names you want setting and getting those private fields:
// ...
private int IdStatus;
public int StatusId {
get { return IdStatus; }
set { IdStatus = value; }
}
// ...