I've an UI (angular JS) where user would want to be able to add,update or delete multiple schedules for a given SoftwareImage (see the API model below) and from the backend(ASP.net web api) I want to be able to handle these cases,following is the algorithm we have between UI and backend but it seems a very hacked way,I want to get opinion from experts on how do you handle such scenarios?
namespace Dashboard.Model.ApiModels
{
public class PostcommitSchedule
{
public string SoftwareImage { get; set; }
public List<PostcommitdayTime> PostcommitdayTime { get; set; }
}
public class PostcommitdayTime
{
public string day { get; set; }
public string Time { get; set; }
}
}
SELECT query:
SELECT si.software_image,pbs.day_of_week_id,pbs.time_of_day FROM postcommitbuild_schedule pbs
join software_images si on si.software_image_id=pbs.software_image_id
where si.software_image='LNX.LA.3.6'
ALGORITHM
If empty object
Delete all records
Else
Run a select query(see above) to see if there are any existing records for the given SoftwareImage(SI)
If records exits
Delete the existing records
Insert the new records
Else
Insert the new records
Related
I am trying to populate a combox box with a list of local office contact names from a database using the following Objects, Entity Framework and LINQ. It is not returning any results. Can anyone please help with this?
The classes look like this.
public class OfficeContact
{
[Key]
public int OfficeContactId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
public class Office
{
[Key]
public int OfficeId { get; set; }
public string Region { get; set; }
public string Address { get; set; }
public string City { get; set; }
[Display(Name = "OfficeContact")]
public virtual int OfficeContactId { get; set; }
[ForeignKey("OfficeContactId")]
public virtual OfficeContact OfficeContacts { get; set; }
}
The LINQ looks like this.
private void cbAddress_SelectionChangeCommitted(object sender, EventArgs e)
{
var localContact = from office in context.Offices.ToList()
where office.OfficeContacts.Equals(office.OfficeContactId)
select Name;
cbLocalOfficeContactName.DataSource = localContact.ToList();
}
First thing, remove the .ToList() from in context.Offices. A ToList() here would cause EF to load all offices from the DB before applying the Where clause.
Next, the following Where clause doesn't make any sense:
where office.OfficeContacts.Equals(office.OfficeContactId)
This is more like a Join clause, not a Where condition. When EF is set up with navigation properties, the join between related entities is handled entirely behind the scene.
If you want to select the Office Contact Name for every office, you need only to Select the name from the related entity. You can then get the data prior to loading with ToList():
var localContacts = (from office in context.Offices
select office.OfficeContacts.Name).ToList();
The Where clause would be where you only want contacts from specific offices that match a condition. Such as if you only want contact names for an office in a particular Region:
var localContacts = (from office in context.Offices
where office.Region = localRegion
select office.OfficeContacts.Name).ToList();
Where localRegion is a passed in or computed value to limit your office selections.
From there you can put a breakpoint here, let it execute, and see if you get any localContacts. If you are not seeing any data then the most common culprit is that at runtime the DbContext is using a different connection string than you expect and it doesn't have the data you expect it to find. Double check the connection string in your web.config or .exe.config file. Common causes for this issue is moving the DbContext and entities to a different assembly and updating the connection string in the DLL's app.config where it doesn't reflect the setting still in the main application's configuration.
try this
var localContacts = context.Offices
.Select(o=>o.OfficeContacts.Name)
.ToList();
cbLocalOfficeContactName.DataSource = localContacts;
In my website, I want to show projects with its associated technologies and their technologiesId for each project. so I am using a stored procedure and I have three tables -
Projects
Technologies
ProjectTechnologies (Relational table for Project and Technologies)
I am using procedure dbo. GetData and use this query in the procedure-
SELECT pt.ProjectId, p.ProjectTitle, p.ShortContent, p.ThumbImage,t.TechnologyName, pt.TechnologyId FROM dbo.ProjectTechnologies as pt
INNER JOIN dbo.Projects p
ON pt.ProjectId =p.ProjectId
INNER JOIN dbo.Technologies t
ON pt.TechnologyId = t.TechnologyId
So It will Return Project table Columns many times because of each project have many technologies, but now the problem is on the c# code I am using View model to get data -
public class ProjectViewModel
{
public int ProjectId { get; set; }
public string ProjectTitle { get; set; }
public string ShortContent { get; set; }
public string ProjectImage { get; set; }
public string ThumbImage { get; set; }
public List<string> TechnologyName { get; set; }
public List<string> TechnologyId { get; set; }
}
So now, I want to get List of Projects further List of technology name and technology Id. How to manipulate data after getting from SQL in this model form. If I will use for loop then it will very long code and also need to check many conditions so is there any way to map the model with data easily?
I have n number of services and under each service there will be 2 routes(some times more than 2). Under each route there are n number of stops. I am getting values from db as a table in below column order
ServiceId, Service Name,serviceLine color,RouteId, Route Name, Stop Id, Stop Name, Latitude, Longitude.
I want to convert it an object list of below format
public class Service
{
public string ServiceId { get; set; }
public string ServiceName { get; set; }
public string ServiceLineColor { get; set; }
public List<RouteData> RouteList { get; set; }
}
public class RouteData
{
public string RouteId { get; set; }
public string RouteCode { get; set; }
public string RouteName { get; set; }
public List<StopData> stopList { get; set; }
}
public class StopData
{
public string StopCode { get; set; }
public string StopName { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
public string StopType { get; set; }
}
Is there any easy way in linq to convert data in to below format? I wanted to avoid looping.. since i am getting nearly 1k records from db. Please help me to solve this issue.
Or is it best to use db calls to format data. i didn't prefer that because if there is 50 services i need to do 50 db calls and again have to do data formatting logic.
To avoid looping over the data structure each time, you could build up additional dictionaries that provide fast access of the objects by id:
var myServiceIndex = new Dictionary<string, Service>()
var myRouteDataIndex = new Dictionary<string, RouteData>()
Service service;
RouteData routData;
foreach (var record in databaseRecords)
{
if (myRouteDataIndex.TryGetValue(record.RouteId, out route))
{
// add stop data
}
else if (myServiceIndex.TryGetValue(record.ServiceId, out service)
{
// add route data
// add stop data
}
else
{
// add service
// add route data
// add stop data
}
}
You have a number of stops, and for each stop entry in database you have to map it to a C# object. In this case, looping is inevitable, as far as I see. Linq, and eg. entity framework, use looping internally.
One option is to use entity framework or Linq to SQL. It will give you strong type classes representing each DB table. But you have to change your DB schema and use foreign keys to link service, route, and stops.
C# code would look exactly like yours, which is auto generated by entity framework and in-sync with DB schema.
Second option is to convert manually. Note, your current schema doesn't complient with Third normal form. If you don't want to change your schema, you could read and generate them using group by clause.
I've started learning NoSQL on an example of RavenDB. I've started with a simplest model, let's say we have topics that were created by users:
public class Topic
{
public string Id { get; protected set; }
public string Title { get; set; }
public string Text { get; set; }
public DenormalizedUser User { get; set; }
}
public class DenormalizedUser
{
public string Id { get; set; }
public string Name { get; set; }
}
public class User
{
public string Id { get; protected set; }
public string Name { get; set; }
public DateTime Birthdate { get; set; }
//some other fields
}
We don't need the whole User for displaying a Topic, so I've denormalized it to DenormalizedUser, containing an Id and a Name.
So, here are the questions:
1) Is this approach correct for NoSQL?
2) How to handle cases when User changes the Name? Do I need to manually update all the Name fields in denormalized classes?
Shaddix you can use the Raven DB Include function to load the User using the UserId from your topic.
var topic = _session.Load<Topic>(topicId)
.Customize(x => x.Include<Topic>(y => y.UserId));
var user = _session.Load<User>(topic.UserId);
The Load for Topic will 'preload' the User and both Loads will only result in one GET request. (I couldn't reply directly to your response to Ayende due to my reputation).
You also use the alternative (and probably clearer) .Include() function without Customize().
http://docs.ravendb.net/consumer/querying/handling-document-relationships.html
shaddix,
You don't need to denormalize, you can hold a reference to the id and then Include that when you load from the server
1) Yes, this approach works fine and the result is, that you only need to load the topic-document when you want to display it along with the name of its user. However, as Ayende states, the perfomance will be nearly the same as if you didn't denormalize the user and just include it when needed. If you don't worry about multiple-server deployment I recommend that approach.
2) If you really want to denormalize the user, then you can update all topics referencing this user simply with a set based operation. Look at this: http://ravendb.net/faq/denormalized-updates
I currently have an Entity Framework model that collects data from a legacy database and I am currently using an int on my Id properties
I am attempting to build a search box with autocomplete capabilities and want to have the autocomplete function to return a subset of records based on whether the sample id either contains or starts with (final design decision not made yet) and I am running into problems with converting the integer id to a string as I would normally use a recs.Id.toString().StartsWith(recordId) but this is apparently not supported by the Entity Framework
Is there a way around this limitation ?
My code looks like the following
Model:
public class Sample
{
public Sample()
{
Tests = new List<Test>();
}
public int Id { get; set; }
public DateTime SampleDate { get; set; }
public string Container { get; set; }
public string Product { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public virtual SamplePoint SamplingPoint { get; set; }
public virtual SampleTemplate SampleTemplate { get; set; }
public Customer ForCustomer { get; set; }
public virtual ICollection<Test> Tests { get; set; }
}
and the query I am currently trying to apply to this model
[HttpGet]
public JsonResult AutoComplete(string partialId)
{
var filteredSamples =
repo.AllSamples.Where( s =>
String.Compare(s.Status, "A", false) == 0
&& (s.Id.ToString()).StartsWith(partialId)
).ToList();
return Json(filteredSamples, JsonRequestBehavior.AllowGet);
}
Any ideas would be awesome I am out of ideas at this point
No matter what you do, this is going to result in some awful performance on large datasets, because you will not be able to use any indices. My recommendation would be to use a trigger or scheduled task to store the leading digit in a separate field and filter on that.
I ended up adding a view for autocomplete data and converting the data to string in the select statement and this solved my issue
Wild thought: how about your create a computed, persisted column on your database table, that converts your ID (INT) into a string?
Then you could:
put an index on that column
use a simple string comparison on that string column
Basically, you need this:
ALTER TABLE dbo.YourTable
ADD IDAsText AS CAST(ID AS VARCHAR(10)) PERSISTED
Now update you EF model - and now you should have a new string field IDAsText in your object class. Try to run your autocomplete comparisons against that string field.