How to get Specific column of a table in webAPI method - c#

I have a MVC4 application with a WebApi method which is getting entire table data from database. Now i want to extract only two columns from it. How can I do it?
I know that arrays will be used to do so but don't know the syntax in .net.
This is my WebAPi function which is getting the entire table data from the SQL server database:
namespace BRDCEP_MIS.Areas.BRDCEP.Controllers
{
public class WebApiController : ApiController
{
//api get method.
//[Route("WebApi/GetPscTargets")]
public HttpResponseMessage Get() {
using (ApplicationDbContext db = new ApplicationDbContext())
{
List<PscDistrictTargets> xx = new List<PscDistrictTargets>();
xx = db.PscDistrictTargetss.ToList();
//xx.ID = Convert.ToString(DATA);
HttpResponseMessage response = new HttpResponseMessage();
response = Request.CreateResponse(HttpStatusCode.OK, xx);
return response;
}
}
}
}

You can use the Select method and do a projection on only those properties you needed to an an object of your DTO/view model to represent this data, in your LINQ query.
So create a DTO class to represent the data you want with only those properties,
public class MyDto
{
public int TargetId { set; get; }
public string TargetName { set; get; }
}
Now update your LINQ query use the Select method to get only those properties and project those our dto object.
var items = db.PscDistrictTargetss
.Select(f => new MyDto { TargetName = f.Name,
TargetId = f.Id})
.ToList();
return Request.CreateResponse(HttpStatusCode.OK, items );
Assuming PscDistrictTargets entity class has a Name and Id property. Update that part based on your actual property names.

Related

What is the correct way to do many to many entity relation insert?

I am using .net5 and EntityFrameworkCore 5.
I have a many to many relationship between Questions and Categories.
I am using Code first generation.
public class Question
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Category> Categories { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Question> Questions { get; set; }
}
I want to know how to add a Question with Categories.
I tried this :
[HttpPost]
public async Task<ActionResult<Question>> PostQuestion(Question question)
{
question.Categories.Add(new Category() { Id = 1 });
_context.Questions.Add(question);
await _context.SaveChangesAsync();
return CreatedAtAction("GetQuestion", new { id = question.Id }, question);
}
And I have a Category with the Id : 1 in my database.
However I get this exception
SqlException: Cannot insert explicit value for identity column in table 'Categories' when IDENTITY_INSERT is set to OFF.
What is the correct way to do many to many entity relation insert ?
The truly correct and intended way is to load the related entities into context before adding them to the "links" collection.
Let say you have a list of existing related entity keys:
var categoryIds = new[] { 1, 3, 4 };
Then you can use the Find method to load the corresponding entities into context and obtain their instances:
question.Categories = categoryIds
.Select(id => _context.Categories.Find(id))
.ToList();
The drawback is that it makes N database roundtrips to load the data you might not really need.
It can be made with just one additional database roundtrip by issuing Contains based query instead:
question.Categories = await _context.Categories
.Where(e => categoryIds.Contains(e.Id))
.ToListAsync();
If you really don't want the related entities, following are some other ways.
If the context lifetime is scoped to just that call, then you can use fake (stub) entities as with your attempt, but you have to Attach them to the context to let EF Core treat them as existing rather than as new if you don't do that:
question.Categories = categoryIds
.Select(id => _context.Attach(new Category { Id = id }))
.ToList();
Another way is to insert directly entries in the shadow join dictionary type entity set. But it requires knowing the conventional names of the join entity type and its shadow FKs, so this is type unsafe.
Also you need to first to Add the entity in order to have its temporary key available:
var entry = _context.Questions.Add(question);
Then for the shown model you have
var joinEntityName = "CategoryQuestion";
var fromPK = nameof(Question.Id);
var fromFK = "QuestionsId";
var toFK = "CategoriesId";
Actually these can be obtained from the EF Core metadata, which would make it safer:
var navInfo = entry.Collection(e => e.Courses).Metadata as Microsoft.EntityFrameworkCore.Metadata.ISkipNavigation;
var joinEntityName = navInfo.JoinEntityType.Name;
var fromPK = navInfo.ForeignKey.PrincipalKey.Properties.Single().Name;
var fromFK = navInfo.ForeignKey.Properties.Single().Name;
var toFK = navInfo.Inverse.ForeignKey.Properties.Single().Name;
Then the insert code is:
var fromId = entry.CurrentValues[fromPK]; // the temp PK
db.Set<Dictionary<string, object>>(joinEntityName).AddRange(
categoryIds.Select(toId => new Dictionary<string, object>
{
{ fromFK, fromId },
{ toFK, toId },
}));

Azure Document DB UpdateDoc

I am starting off with azure document db. I was trying to update an existing document. When I use the following query everything works:
dynamic Team2Doc = client.CreateDocumentQuery<Document>(documentCollection.DocumentsLink).Where(d => d.Id == "t002").AsEnumerable().FirstOrDefault();
Team2Doc.TeamName = "UPDATED_TEAM_2";
await client.ReplaceDocumentAsync(Team2Doc);
but if use the below code:
dynamic Team2Doc = client.CreateDocumentQuery<Document>(documentCollection.DocumentsLink).Where(d => d.TeamName== "team1").AsEnumerable().FirstOrDefault();
Team2Doc.TeamName = "UPDATED_TEAM_2";
await client.ReplaceDocumentAsync(Team2Doc);
I get this error:
"The best overloaded method match for
'Microsoft.Azure.Documents.Client.DocumentClient.ReplaceDocumentAsync(Microsoft.Azure.Documents.Document,
Microsoft.Azure.Documents.Client.RequestOptions)' has some invalid
arguments"
Is there anyway to retrieve a document by one of the properties and update the document?
The where clause is trying to query the property TeamName which does not exist in Document class.
Changing the type of the queryable to your data model should fix it.
For example, say you have the following data model:
public class EmployeeDocument : Document
{
// Other properties that you may have similarly defined ....
public class string TeamName
{
get
{
return this.GetValue<string>("TeamName");
}
set
{
this.SetValue("TeamName", value);
}
}
}
Then you can modify your query like this:
var team2Doc = client.CreateDocumentQuery<EmployeeDocument>(documentCollection.DocumentsLink).Where(d => d.TeamName== "team1").AsEnumerable().FirstOrDefault();
team2Doc.TeamName = "UPDATED_TEAM_2";
await client.ReplaceDocumentAsync(team2Doc);
Note that you have to use the EmployeeDocument, instead of the Document class, while creating the document queryable. That will let you query on EmployeeDocument properties.
SQL Version
Creating a document model for each of your existing data models may not be feasible if you have a large number of data models. In that case you may want to try out the SQL query syntax.
Refer to Aravind's answer in this post. The example he uses is for deleting documents, but it can be easily modified to update them too.
You can also create a model with Id:
public class Employee
{
[JsonPropery("id")]
public class string Id { get; set; }
public class string TeamName { get; set; }
}
And then replace the document using it's Id:
var employee= client
.CreateDocumentQuery<Employee>(documentCollection.DocumentsLink)
.Where(d => d.TeamName== "team1")
.AsEnumerable()
.FirstOrDefault();
employee.TeamName = "team2";
var documentUri = UriFactory.CreateDocumentUri(databaseName, collectionName, employee.Id);
await client.ReplaceDocumentAsync(employee);

Returning IQueryable type: The entity or complex type '' cannot be constructed in a LINQ to Entities query

I am running a query to populate options in a single select drop down menu. When I debug the function below, the query variable contains the resultset that I am expecting. However when I skip next to where it should be returned to, I get the error:
'The entity type or complex type 'Models.zz_Member' cannot be constructed in a LINQ to Entities query."
public IQueryable<zz_Member> GetMembers(string searchText)
{
var _db = new Portal.Models.AuthorizationContext();
IQueryable<zz_Member> query = _db.zz_Members;
return query //.Where(a => a.memLastName.Contains(searchText))
.Select(a => new zz_Member()
{
ID = a.ID,
memFirstName = a.memFirstName,
memLastName = a.memLastName
}
);
}
The zz_Member model object is defined as:
public class zz_Member
{
[ScaffoldColumn(false)]
public int ID { get; set; }
public string memFirstName { get; set; }
public string memLastName { get; set; }
}
The error is thrown when I try to convert to an IList, but when I check the value of memList using the debugger, it shows the error text in the results view.
IQueryable<zz_Member> memList = GetMembers(e.Text);
IList<zz_Member> memList2 = memList.ToList();
I have also tried writing the GetMembers functions to return the list as so:
public IList<zz_Member> GetMembers(string searchText)
{
var _db = new WWCPortal.Models.AuthorizationContext();
return (from m in _db.zz_Members
where m.memLastName.Contains(searchText)
select new zz_Member { ID = m.ID, memFirstName = m.memFirstName, memLastName = m.memLastName }).ToList();
}
Any hints or answers to why the resultset appears to not be getting returned to the caller and put into memList? Thanks.
You cannot use framework dependant/generated entities in projection (with select new), hence the error.
Looks like you are trying to select specific columns instead of all columns, your options are
Project to a new class with those specific members
return all fields/columns for your entities like:
Code:
return query.Where(a => a.memLastName.Contains(searchText)); //without `select new`

How to return the ID of each record after insert using EF

I have a data class with nested Lists. A simplified example (not real code):
public class Movie
{
public Int32 TVIndex;
public string MovieName;
public string MovieRating;
public string MovieRuntime;
public List<Actor> MovieActors;
public List<MovieArt> MovieImages;
}
public class Actor
{
public string ActorName;
public string ActorRole;
}
public class MovieArt
{
public string ImagePath;
}
List<Movie> myMovies = new List<Movie>();
This may contain many movies and each movie may contain many Actors and many MovieArt.
I pass this list to a web service that inserts the records into tables using DataEntityModel.
Something Like..
public void InsertMovies(List<Movie> request)
{
using (TransactionScope scope = new TransactionScope())
{
using (MyMovieStorageEntities DbContext = new MyMovieStorageEntities())
{
foreach (Movie m in request)
{
Movies movie = new Movies();
movie.MovieName = m.MovieName;
movie.MovieRating = m.MovieRating;
movie.MovieRuntime = m.MovieRuntime;
DbContext.DBMovies.Add(movie);
foreach (Actor a in m.MovieActors)
{
Actors actor = new Actors();
actor.ActorName = a.ActorName;
actor.ActorRole = a.ActorRole;
DbContext.DBActors.Add(actor);
}
for (MovieArt i in m.MovieImages)
{
MovieArt artwork = new MovieArt();
artwork.FileName = i.FileName;
DbContext.DBMovieArt.Add(artwork);
}
}
DbContext.SaveChanges();
}
}
}
In the Movie table is an Identity column and I need to return the identity for each inserted record for use in the client app.
I am new to DataEntity and not really sure where to start. All the searching I have done hasn't really helped. Any pointers?
Don't lose the references to your entity framework objects (e.g. add them to a list), and after SaveChanges(), the object property containing the primary key will be automatically updated with the ID.
See here for more info
How can I get Id of inserted entity in Entity framework?
EF automatically returns the ID. movie.ID gives you the last inserted ID you can use it or return it from your method to use somewhere else.

ASP.NET C# Entity Framework - How to update Foreign Key properly? - Part 2

This question is like a Part 2 of my previous one here!
Here are things I learned and hoping to be true:
Do not use Data Entity Context as Static
Dispose the data context after used -usually after one time-
Pass parameters into UPDATING Entity method instead of the Entity
(which I'll explain and in here my crossroad lies)
Here is my modified code:
public class ManagerBase
{
private NoxonEntities _entities = null;
public NoxonEntities Entities
{
get
{
if (_entities == null)
_entities = new NoxonEntities();
return _entities;
}
}
}
//Managers uses ManagerBase class as a Base class
MemberManager currentMemberManager = new MemberManager();
currentMemberManager.Save(memberId, username, password, languageId);
//MemberManager class
public Member Save(long memId, string username, string password, int langId)
{
using (var Context = base.Entities)
{
var Data = Context.Member.First(c => c.Id == memId);
Data.Username = username;
Data.Password = password;
Data.Language = Context.Language.First(c => c.Id == langId); //Gets the foreign entity
Context.SaveChanges();
return Data;
}
}
This works without exception. But normally this SAVE method is an implemented method by an interface. So, I'd rather to pass an OBJECT value to the SAVE method than passing all the fields like above.
For example I'd like to use this:
//Member is an EntityFramework Object which was created during EF Model when I added by visual studio
//Filter is the method that returns an EntityFramework Object from EF (and eventually database) with given some arguments
//SomeArguments could be MemberId = 2
Member modifiedMember = currentMemberManager.Filter(someArguments);
modifiedMember.UserName = "newvalue";
currentMemberManager.Save(modifiedMember);
In the SAVE method perhaps I could use like this:
public Member Save(Member modifiedMember)
{
using (var Context = base.Entities)
{
var Data = Context.Member.First(c => c.Id == modifiedMember.Id);
Data.Username = modifiedMember.Username;
Data.Password = modifiedMember.Password;
Data.Language = Context.Language.First(c => c.Id == modifiedMember.LanguageId); //Gets the foreign entity
Context.SaveChanges();
return Data;
}
}
If I am gonna use this just like the one right above, I think I should NOT use the passing object EF Object and instead perhaps I should use some other class that I'll write just to map the parameters to the EF Member Entity.
First question: Is this a good approach?
public class MyMember
{
public long Id { set; get; }
public string Username { set; get; }
public string Password { set; get; }
public int LanguageId { set; get; }
}
MyMember.Username = "NewValue";
MyMember.LanguageId = 4; //4 as in new value
currentMemberManager.Save(MyMember); //As you can see MyMember is not an EF Entity in here
But this will take long time since there is already some written code.
Second question: Can't I use an EF Entity object OUTSIDE and modify it there to save it IN the MemberManager class?
Again, thank you very much for your help in advance.
Here is the answer:
How to update entity?
And I thank you for the ones who helped me.

Categories

Resources