best way to convert database table in codefirst to model - c#

i have table of news , and i need convert to model .
like this :
i need pass to view NewsModel and i have table News .
i convert that :
public ActionResult EditNews(int NewsID)
{
NewsModel model = new NewsModel();
var editservice = _NewsSerivce.NewsByID(NewsID);
model.NewsID = editservice.NewsID;
model.NewsHeader = editservice.NewsHeader;
model.NewsTitle = editservice.NewsTitle;
model.NewsText = editservice.NewsText;
model.NewsDefaultFile = editservice.NewsDefaultFile;
model.CatID = editservice.CatID;
model.SubCatID = editservice.SubCatID;
DropDownCategory(model);
return View("Edit",model);
}
it work but i need use best way for convert .
what best way ?

You can use this nuget:
http://automapper.org/
Documentation is here:
https://github.com/AutoMapper/AutoMapper/wiki/Getting-started
I dont know how your class looks so i make my class:
public class TestClass
{
public int NewsID { get; set; }
public string NewsHeader { get; set; }
public string NewsTitle { get; set; }
public string NewsText { get; set; }
public string NewsDefaultFile { get; set; }
public int CatID { get; set; }
public int SubCatID { get; set; }
}
and my mapping class:
public class NewTestClass
{
public int NewsID { get; set; }
public string NewsHeader { get; set; }
public string NewsTitle { get; set; }
public string NewsText { get; set; }
public string NewsDefaultFile { get; set; }
public int CatID { get; set; }
public int SubCatID { get; set; }
}
i have map this class like this:
TestClass tc = new TestClass { CatID = 1, NewsID = 1, SubCatID = 1, NewsDefaultFile = "test1", NewsHeader = "test2", NewsText = "test3", NewsTitle = "test4" };
Mapper.Initialize(cfg => cfg.CreateMap<TestClass, NewTestClass>());
var config = new MapperConfiguration(cfg => cfg.CreateMap<TestClass, NewTestClass>());
var mapper = new Mapper(config);
NewTestClass ntx = Mapper.Map<NewTestClass>(tc);
Console.WriteLine(ntx.NewsID);

in my viewpoint, this link is the best of the method to Entity Framework Code First to an Existing Database.
In the visual studio go to Project -> Add New Item…
Select Data from the left menu and then ADO.NET Entity Data Model,
Enter BloggingContext as the name and click OK
This launches the Entity Data Model Wizard
Select Code First from Database and click Next
WizardOneCFE
Select the connection to the database you created in the first section and click Next
WizardTwoCFE
Click the checkbox next to Tables to import all tables and click Finish
WizardThreeCFE

Related

Create a list of model values differences

Currently, I'm working on an Angular (front-end) C# (back-end) application. This application uses Entity Framework code first.
I'm going to work with an Activity Log, basically to save changes inside an app Profile section, so I think about the following model for that:
public partial class ProfileActivity : BaseAuditModel, IEntity
{
public string Description { get; set; }
public int ProfileId { get; set; }
public virtual Profile Profile { get; set; }
public int ActivityTypeId { get; set; }
public string OldValue { get; set; }
public string NewValue { get; set; }
}
Well, now on update endpoint (controller), I receive data from the front end as:
[Authorize]
[HttpPost("AddProfile")]
[CleanCache]
public async Task<ActionResult<Profile>> AddProfile(Profile profile)
{
var user = await this.GetUser();
var model = await _profileService.EditProfile(profile, user);
if (model != null) return Ok(model);
return NotFound();
}
My question is right here. How can I compare the received model (with changes) with the current Profile (with no changes yet)? I can get the model without changes by doing a get operation before saving the changes as:
var currentProfile = GetProfile(profile.Id);
But now, how can I identify all the changes between received profile model and the currentProfile?
Profile Model:
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime? DateOfBirth { get; set; }
public int VettingStatusId { get; set; }
public int? RecruiterId { get; set; }
etc..
So, at the end of the date, I can insert into my new table ProfileActivity all the changes where we found the differences.
From your description, I think you wanna compare two objects and put the different properties into a list mdoel. So you can refer to this simple demo:
NuGet Package:
Install-Package ObjectsComparer
Model:
public class ComparedModel
{
public string Description { get; set; }
public string OldValue { get; set; }
public string NewValue { get; set; }
}
Demo:
//current model
var a1 = new ClassA()
{
Id = 1,
FirstName = "AAA",
Age = 23,
LastName = "BB"
};
//new model from frontend
var a2 = new ClassA()
{
Id = 1,
FirstName = "AAA",
Age = 16,
LastName = "BBVV"
};
//receive the different properties
List<ComparedModel> t = new List<ComparedModel>();
var comparer = new ObjectsComparer.Comparer<ClassA>();
IEnumerable<Difference> differences;
var isEqual = comparer.Compare(a1, a2, out differences);
if (!isEqual)
{
foreach (var item in differences)
{
t.Add(new ComparedModel()
{
Description = item.MemberPath,
OldValue = item.Value1,
NewValue = item.Value2
});
}
}
You can see the propertiy name, old value and new value have been inserted into the list model.
=======Update======
You can use reflection, for example:
public static void GetChanges<T>(T a, T b) where T : class {
foreach (var prop in typeof(T).GetProperties()) {
if(prop.GetValue(a) != prop.GetValue(b))
System.Diagnostics.Debug.Print(prop.Name);
}
}

Save Related Data (Many to Many) in EF Core 5 without getting the actual records

I am creating a web app for Lunch Reservation.
public class Food : BaseEntity
{
public int FoodId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
public string PhotoPath { get; set; }
public ICollection<Menu> Menus { get; set; }
/*public ICollection<LunchReservation> LunchReservations { get; set; } omit */
}
public class Menu : BaseEntity
{
public Menu()
{
DateCreated = DateTimeOffset.Now;
DateModified = DateTimeOffset.Now;
}
public int MenuId { get; set; }
[Column(TypeName = "date")]
public DateTime MenuDate { get; set; }
public bool IsPublished { get; set; }
public ICollection<Food> Foods { get; set; }
/*public ICollection<LunchReservation> LunchReservations { get; set; } omit */
}
Everything is ok, but when I want to create a menu that can have 1 food or more I get an error.
this is my Dto for creating a Menu
public class MenuCreationDto
{
public int[] FoodIds { get; set; }
public string MenuDate { get; set; }
}
and this code does not work for saving.
var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();
Menu newMenu = new()
{
MenuDate = menuDateInGregorian,
Foods = foods
};
await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();
but for saving foods this code is working but I don't want to get foods from the database to just make a menu.
var foods = _db.Foods.Where(f => menuCDto.FoodIds.Contains(f.FoodId)).ToList();
Menu newMenu = new()
{
MenuDate = menuDateInGregorian,
Foods = foods
};
await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();
what can I do for saving a menu to the database without getting actual foods from the database?
You can use fake (a.k.a. stub) entities as in your non working example
var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();
But before letting EF Core add the parent entity (Menu), you have to let it know that these are "existing" entities, otherwise it will treat them a "new" and will try to insert new Food records, rather than links as intended. You do that by attaching them to the context, which marks them as existing and unchanged:
_db.AttachRange(foods);
The rest of the code will be the same, but now should be working.

Multiple tables with different LINQ queries in a single view

Title says it all, right now I have a single table that is populated from a linq query and I want to add more tables with different linq queries. I'm kinda lost on how would I do that..
I could probably do it if I create different views for each table but I want to have just one view for all. :D
Here's my code: (It's a table for "on going" projects)
Controller:
public ActionResult Index()
{
var project = from x in db.Projects
where x.Project_Status == "Ongoing"
select x;
return View(project);
}
Model:
public class Project
{
[Key]
public int Project_Id { get; set; }
public string Project_Name { get; set; }
public string Project_Detail { get; set; }
public string Project_Status { get; set; }
public int Employee_Id { get; set; }
}
View Model:
public class AdminHomeViewModel
{
public Project Ongoing { get; set; } //table for ongoing projects
public Project NYA { get; set; } //another table for Not Yet Assigned projects
public Employee Free { get; set; } //another table for free employees
public List<Project> OngoingList { get; set; }
public List<Employee> NYAList { get; set; }
public List<Employee> FreeList { get; set; }
}
You are confusing yourself with the different types of models. You should have a clear understanding between View-Model and Data-Model. You should always return View-Model to the View, and not the Data-Model. Data-Model are just the POCO classes which represents your data framework (in this case, each tables). There should be different Data Models for each of your table, which you must be having already based on your entity-framework approach (Code first, Model first or Database first). Then, prepare a single model for your view (as we can bind only one model to one view). Keep all the fields from different Data-Models that you need in that View and pass it along. See the approach below:
Data-Models
public class Project
{
[Key]
public int Project_Id { get; set; }
public string Project_Name { get; set; }
public string Project_Detail { get; set; }
public string Project_Status { get; set; }
public int Employee_Id { get; set; }
}
public class Employee
{
[Key]
public int Employee_Id { get; set; }
public string Employee_Name { get; set; }
public string Employee_Detail { get; set; }
}
View-Model
public class MyViewModel
{
public int Project_Id { get; set; }
public string Project_Name { get; set; }
public string Project_Detail { get; set; }
public string Project_Status { get; set; }
public int Employee_Id { get; set; }
public string Employee_Name { get; set; }
public string Employee_Detail { get; set; }
}
Or
public class MyViewModel
{
public Project proj { get; set; }
public Employee emp { get; set; }
}
Pass it to view as:
public ActionResult Index()
{
MyViewModel model = new MyViewModel();
// You linq query to populate model goes here
return View(model);
}
Update:
From my understanding, you need something like this:
View-Model:
public class AdminHomeViewModel
{
public AdminHomeViewModel()
{
Ongoing = new List<Project>();
NYA = new List<Project>();
Free = new List<Employee>();
}
public List<Project> Ongoing { get; set; } //table for ongoing projects
public List<Project> NYA { get; set; } //another table for Not Yet Assigned projects
public List<Employee> Free { get; set; } //another table for free employees
}
Controller:
public ActionResult Index()
{
AdminHomeViewModel model = new AdminHomeViewModel();
var result1 = (from x in db.Projects
where x.Project_Status == "Ongoing"
select new Project(){
Project_Id = x.Project_Id ,
Project_Name = x.Project_Name,
... //all other assignments goes here
}).ToList();
var result2 = (from x in db.Projects
where x.Project_Status == "blah blah"
select new Project(){
Project_Id = x.Project_Id ,
Project_Name = x.Project_Name,
... //all other assignments goes here
}).ToList();
var result3 = (from x in db.Employee
where x.AnyCondition == "blah blah"
select new Employee(){
Employee_Id = x.Employee_Id ,
Employee_Name = x.Employee_Name,
... //all other assignments goes here
}).ToList();
model.Ongoing = result1;
model.NYA = result2;
model.Free = result3;
return View(model);
}

c#. EF entity sql. How to get entity with related objects?

I have made simple model for example.
public class Publisher
{
public int Id { get; set; }
public string Title { get; set; }
public Address Location { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
public class Address
{
public string Country { get; set; }
public string City { get; set; }
public string Street { get; set; }
public string HouseNumber { get; set; }
}
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public int LanguageId { get; set; }
public int? PublisherId { get; set; }
}
I need to get publishers with related books. I know how to do it using linq to entities. Is it possible to solve a problem using entity sql?
public class CatalogContext : DbContext {...}
public List<Publisher> GetByCity(string city)
{
var result = new List<Publisher>();
string queryString;
queryString = String.Format(#"SELECT VALUE row(a,b)
FROM CatalogContext.Publishers AS a
join CatalogContext.Books AS b on a.Id = b.PublisherId
WHERE a.Location.City = '{0}'", city);
var rows = ((IObjectContextAdapter)_context).ObjectContext.CreateQuery<DbDataRecord>(queryString).ToList();
return ???
}
Query returns required data but it's List<DbDataRecord> - list of pairs <publisher, book>. How to translate it to list of publishers with filled navigation property "Books"?
Is it possible to write query which directly returns List<Publisher>?
you can do the following:
var result = ObjectContext.Publishers.Include("Books").Include("Locations")
.Where(c => c.Location.City = "SOME_CITY").Select(c => c);
Include - basically joins the table.
Then you can drill down to books by doing the following:
var test = result[0].Books;
Why are you using direct sql command instead of Entity Framework code style?

EF4.1 - Attribute Evaluating to null at runtime

I'm using EF4.1 code first to create a simple database app with SQL CE 4 backend. I have a Product class and a CallItem class defined as so:
class CallItem
{
public int id { get; set; }
public float discount { get; set; }
public virtual Product Product { get; set; }
}
class Product
{
public int id { get; set; }
public decimal BaseCost { get; set; }
public int UnitSize { get; set; }
public bool isWasteOil { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
}
edit - When I am creating a collection of CallItems using a LINQ query, I cannot access the attributes of the Product attached to each CallItem, eg
var callItems = from ci in context.CallItems select ci;
foreach(CallItem callItem in callItems)
{
RunSheet nrs = new RunSheet();
nrs.prodCode = callitem.Product.Code;
}
Interrogating the database shows that Productid in CallItems is being populated. However, the following line generates a NullReferenceException during run time:
nrs.prodCode = callitem.Product.Code;
Because callitem.Product is evaluating to null. Is this something to do with lazy loading and if so how can I resolve the issue?
RunSheet is another class, nrs is an instance whose attribute 'prodCode' I want to populate with the CallItem's Product's code.
Thanks!
From that code what you've showed it should work. Have you tried explicit loading?
var callItems = from ci in context.CallItems.Include(c => c.Product) select ci;
foreach(CallItem callItem in callItems)
{
RunSheet nrs = new RunSheet();
nrs.prodCode = callitem.Product.Code;
}
public class CallItem
{
public int Id { get; set; }
public float Discount { get; set; }
public virtual Product Product { get; set; }
}
public class Product
{
public int Id { get; set; }
public decimal BaseCost { get; set; }
public int UnitSize { get; set; }
public bool IsWasteOil { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
}
using (var context = new StackOverFlowContext())
{
var p = new Product
{
Id = 1,
BaseCost = 200,
Code = "Hola",
Description = "Soe description",
Ingredients = "Some ingredients",
IsWasteOil = true,
Name = "My Product",
UnitSize = 10
};
var item = new CallItem
{
Id = 101,
Discount = 10,
Product = p
};
context.CallItems.Add(item);
context.SaveChanges();
var result = from temp in context.CallItems
select temp;
Console.WriteLine("CallItem Id"+result.First().Id);
Console.WriteLine("ProductId"+result.First().Product.Id);
}
I wrote the above code with the following output
CallItemId 1
ProductId 1
The sql Profiler showed this
SELECT TOP (1)
[c].[Id] AS [Id],
[c].[Discount] AS [Discount],
[c].[Product_Id] AS [Product_Id]
FROM [dbo].[CallItems] AS [c]
It was too long for a comment ,so i put it here .

Categories

Resources