Why it produces additional SQL queries when use AutoMapper even though all data have been retrieved from database? - sql

I'm using LINQ and AutoMapper in my ASP.NET web project to retrieve data from database. Here is my controller action to retrieve and list all data from database:
public ActionResult ListPlans()
{
db.Database.Log = (log) => System.Diagnostics.Debug.WriteLine(log);
var listPlan = db.Plans?.OrderByDescending(p => p.PlanId).ToList();
var listPlanViewModels = Mapper.Map<IEnumerable<PlanViewModel>>(listPlan);
return View(listPlanViewModels);
}
When I debug it step by step with Visual Studio, I noticed all data from database have been retrieved and put into memory after this line below was executed:
var listPlan = db.Plans?.OrderByDescending(p => p.PlanId).ToList();
Here is the SQL query produced by above line:
SELECT
[Extent1].[PlanId] AS [PlanId],
[Extent1].[PlanName] AS [PlanName],
[Extent1].[PlanStatus] AS [PlanStatus],
[Extent1].[TemplateId] AS [TemplateId],
FROM
[dbo].[Plan] AS [Extent1]
ORDER BY
[Extent1].[PlanId] DESC
But I noticed it produces additional SQL queries to database when executed this line below:
var listPlanViewModels = Mapper.Map<IEnumerable<PlanViewModel>>(listPlan);
It produces SQL query for each row of data in database, the SQL query shows below:
SELECT
[Extent1].[TemplateId] AS [TemplateId],
[Extent1].[Name] AS [Name],
[Extent1].[Description] AS [Description],
[Extent1].[IsActive] AS [IsActive],
FROM
[dbo].[Template] AS [Extent1]
WHERE
[Extent1].[TemplateId] = #EntityKeyValue1
My question is: why does it produce additional SQL queries even though all data in my database table have been retrieved and put into memory?
How to avoid these additional SQL query when using AutoMapper? It caused performance issue because of these additional queries.
Thanks in advance.
Here are my model and view model:
public partial class Plan
{
public int PlanId { get; set; }
public string PlanName { get; set; }
public string PlanStatus { get; set; }
public System.Guid TemplateId { get; set; }
public virtual Template Template { get; set; }
}
public class PlanViewModel
{
[DisplayName("Plan ID")]
public int PlanId { get; set; }
[DisplayName("Name")]
public string PlanName { get; set; }
public Guid TemplateId { get; set; }
[DisplayName("Template")]
public string TemplateName { get; set; }
[DisplayName("Status")]
public string PlanStatus { get; set; }
}

Related

Error while inserting in a table containing identity column System.Data.Entity.Infrastructure.DbUpdateException

In my ASP.Net MVC 4 project I'm trying to insert data into a table which has identity an auto-increment column (ACTIVITYID), which is the Primary Key.
Table Class
public partial class ACTIVITY
{
public decimal ACTIVITYID { get; set; }
public Nullable<decimal> CALLTICKETNUMBER { get; set; }
public string ACTION { get; set; }
public Nullable<long> STATUSIDATTHETIMEOFACTION { get; set; }
public short RECORDFORDISPLAY { get; set; }
public Nullable<System.DateTime> ACTIVITYDATE { get; set; }
public string USER_ { get; set; }
public virtual CALLTICKET CALLTICKET { get; set; }
}
Upon calling the following method generates exception
public static void AddActivity(long ticketNumber, string action, string userId, int? previousStatusId = null)
{
var newActivity = new ACTIVITY
{
ACTION = action,
ACTIVITYDATE = System.DateTime.Now,
CALLTICKETNUMBER = ticketNumber,
STATUSIDATTHETIMEOFACTION = previousStatusId,
USER_ = userId,
};
dbOraContext.ACTIVITies.Add(newActivity);
dbOraContext.SaveChanges();
}
While viewing ACTIVITies.Add(newActivity) ACTIVITYID is inserting with value 0.
On tracing the inner exception following exception is displayed:
{"ORA-00001: unique constraint (ATM_CRM.PK_ACTIVITY) violated"}
Also, an exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred.
Earlier I have worked with MS SQL Server, and never encountered such a problem. Auto-increment column should automatically get its value.
Note that I'm working on Oracle DB.

Retrieve Big data using EF

I have two tables "Kelime"
public class Kelime
{
public int ID { get; set; }
public string Word { get; set; }
public DateTime Date { get; set; }
}
and "Anlam"
public class Anlam
{
public int ID { get; set; }
public string Meaning { get; set; }
public DateTime Date { get; set; }
public int Kelimesi_ID { get; set; }
[ForeignKey("Kelimesi_ID")]
public virtual Kelime kelime { get; set; }
}
Both tables contains more than 80k datas. I don't think they are very big but I am having problem on this query:
Repository<Kelime> _rk = new Repository<Kelime>();
Repository<Anlam> _ra = new Repository<Anlam>();
IEnumerable<int> kelimeIdler = _ra.All().Select(s => s.Kelimesi_ID).Distinct();
int _kelimecik= _rk.Find(w => !kelimeIdler.Contains(w.ID)).ID;
or Kelime _kelimecim = _rk.All().Where(w => !kelimeIdler.Contains(w.ID)).FirstOrDefault();
I am trying to take the "Kelime", "Kelime List" or its "id" it doesn't matter which are not in my "Anlam" table. There is a timeout when it comes to "contains" part. I tried to write non clustered index but it doesn't accept subquery. What should I do to achieve what I want? Thank you very much.
private static DataContext _context;
public static DataContext ContextOlustur()
{
if (_context == null)
{
_context = new DataContext();
}
return _context;
}
Adding this pattern to my data context class solved my problem. Because my queries used two different context that's why it was getting problem to connect database and got time out. This pattern prevents creating another context.

Returning a String from a SQL query in MVC Entity Framework 6 Controller

I want to execute a basic SQL query (e.g. "SELECT string FROM table WHERE criteria = TRUE) on MVC Entity Framework 6. The returned type is to be a string. I have tried many possible things but they return the SQL query string or something completely irrelevant, such as:
SELECT [Extent1].[Fname] AS [Fname]
FROM [dbo].[Developer] AS [Extent1]
WHERE ([Extent1].[Login] = #p__linq__0)
OR (([Extent1].[Login] IS NULL) AND (#p__linq__0 IS NULL))
I have the following in my controller:
var data = db.Developers.Where(y => y.Login.Equals(username)).ToList();
This is my Developers class:
public partial class Developer
{
public int PersonID { get; set; }
public string Fname
{
get { return Fname.ToString(); }
set { Fname = value;}
}
public string Lname { get; set; }
public string Developer1 { get; set; }
public string Login { get; set; }
public Nullable<bool> IsManager { get; set; }
public Nullable<bool> IsPF { get; set; }
public Nullable<bool> IsLW { get; set; }
public string Prov { get; set; }
}
I would like to get the string that this query returns.
Somehow this works when this is made to a List and passed to the View model, where it is displayed using #Html.DisplayFor().
Is there a way to execute my SQL command in my controller and get a string value in return?
FirstOrDefault() to return the first element, in this case there is only one.
You should include a validation if username doesnt exist.
Developer myDeveloper = db.Developers
.Where(y => y.Login.Equals(username))
.ToList()
.FirstOrDefault();
return myDeveloper.Lname;

Generate meta data from EntityFramework with partial class

I have a class like
using System;
using System.Collections.Generic;
public partial class Order
{
public Order()
{
this.OrderDetails = new HashSet<OrderDetail>();
}
public int OrderID { get; set; }
public string OrderNo { get; set; }
public System.DateTime OrderDate { get; set; }
public int BuyerID { get; set; }
public int UserID { get; set; }
public virtual Buyer Buyer { get; set; }
public virtual User User { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
}
which is provide by EntityFramework.
I have got meta data of the entityframework properly. But I want to add new two Columns as follows
public partial class Order
{
public string BuyerName { get; set; }
public string UserName { get; set; }
}
"After adding new columns when I fetch metadata but system does not return "BuyerName" and UserName" in metadata. what should Do?
I think "BuyerName" and UserName" are two new columns added to "Order" table.
In this case you need to update the Database Model (*.edmx file) (Update Model From DataBase) to get the mapping information for these new columns.
If you want to add only these properties to the Order class without any real columns in the database, then no need of update the Edmx file.

Querying data from a child table in .Net Mobile service

I have two simple models in .net backend based Azure Mobile Service Project, as shown below & I am not able to query the child table (querying parent table, UserItem, works just fine)
(The Id is nvarchar(128) & is autogenerated as newId by DB)
public class AnswerItem: EntityData
{
public string Content { get; set; }
public UserItem By { get; set; }
public QuestionItem ForQuestion { get; set; }
public double Rating { get; set; }
public string Comment { get; set; }
}
& a child to this UserItem Table as shown below
public class QuestionItem: EntityData
{
public string Content { get; set; }
public bool IsAnswered { get; set; }
public int NumberOfAnswers {get; set;}
public UserItem By { get; set; }
public string ById { get; set; }
public string AtLocation { get; set; }
}
As you notice, the QuestionItem has a FK relationship to UserItem table on ById field (Referencing Id field in UserItem Table)
The issue is I am getting a Bad Request error when I try to query the data from child table
Following are some queries that I tried
private IMobileServiceTable<QuestionItem> questionTable = App.MobileService.GetTable<QuestionItem>();
questions = await questionTable.Where(x=>x.IsAnswered==true).ToCollectionAsync(); (Does not Work)
questions = await questionTable.Where(x=>x.ById="UserIdGoesHere").ToCollectionAsync(); (Does Not Work)
questions = await questionTable.Where(x=>x.Content.StartsWith("q")).ToCollectionAsync(); (This Works)
questions = await questionTable.ToCollectionAsync(); (This Works as well)
If I fire a TSQL query in Sql Server Object explorer they all return correct values.
I am at my wits end on what could be wrong with my approach.
Any help is really appreciated.
Thanks
Supreet
Investigating further the Request it was generating was like this
192.168.2.4:50002/tables/QuestionItem?$filter=(byid eq 'myUniqueGuId')
analyzing fiddler output shows this error
"The query specified in the URI is not valid. Could not find a property named 'byid' on type 'x2Service.DataObjects.QuestionItem'"
Off course there is no fields in the table by the name of 'byid' the one I have is called 'ById' Its the JsonProperty adorner that changed it [JsonProperty(PropertyName = "byid")] In my client class.
Removed the Json Property & it worked just fine