How to use DbContext without using Edmx in C#? - c#

Can we use DbContext without adding EDMX in project for Data model here is sample code in which I am trying to save Instance class object with the help of ContextManager which is DbContext.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Objects.DataClasses;
using System.Linq;
using System.Text;
namespace DbContext_test
{
public class ContextManager : DbContext
{
public ContextManager(string connstring)
: base(connstring)
{
}
public override int SaveChanges()
{
//TODO: Write code before saving dataEntity object or fire some event to do so.
return base.SaveChanges();
}
}
public class Instances : EntityObject
{
public int ID { get; set; }
public string InstanceCode { get; set; }
public string InstanceName { get; set; }
}
public class InstanceManager
{
readonly string ConnectionString;
public InstanceManager(string connString)
{
ConnectionString = connString;
}
public void SaveInstance(int id, string instanceCode, string instanceName)
{
SaveInstanceInternal(new Instances { ID = id, InstanceCode = instanceCode, InstanceName = instanceName });
}
public void SaveInstance(Instances instance)
{
SaveInstanceInternal(instance);
}
private void SaveInstanceInternal(Instances instance)
{
var contextManager = new ContextManager(ConnectionString);
contextManager.Entry(instance);
contextManager.SaveChanges();
}
}
}

You can do it using the code first approach instead of the edmx approach.
http://www.entityframeworktutorial.net/code-first/what-is-code-first.aspx

follow this
1) create context class
public class SchoolPlusDBContext : DbContext
{
public SchoolPlusDBContext()
: base("name=SchoolPlusDBContext")
{
}
public DbSet<CategoryMaster> CategoryMaster { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
2) create class
public class CategoryMaster
{
[Key]
public long CategoryID { get; set; }
[Required]
public string CategoryName { get; set; }
[Required]
public string CategoryType { get; set; }
}
3) DA For query execution
public class CategoryDA
{
SchoolPlusDBContext dbContext = new SchoolPlusDBContext();
public List<CategoryMaster> GetAllCategory()
{
return dbContext.CategoryMaster.OrderByDescending(t => t.CategoryID).ToList();
}
public bool AddCategory(CategoryMaster master,string UserName)
{
try
{
master.CreatedBy = UserName;
master.CreatedOn = System.DateTime.Now;
dbContext.CategoryMaster.Add(master);
dbContext.SaveChanges();
}
catch
{
return false;
}
return true;
}
}
}

Related

Auto mapper issue with Object reference not set to an instance of an object

Hi all I do have an issue with my auto mapping objects in my case I need properties to be skipped over and map the db context properties with my custom object
here is how I'm trying to convert the object but i am getting an error
System.NullReferenceException: 'Object reference not set to an instance of an object
var library = await Task.FromResult(mapper.Map<test.WebApi.Dto.Library>(item));
here is my custom mapper class
public class CustomMapper: Profile
{
public CustomMapper()
{
CreateMap<test.WebApi.Models.Library, test.WebApi.Dto.Library>().ForMember(dest => dest.Id, opt => opt.Ignore());
}
}
here are my dto class and the dbcontext classes
using System;
using System.Collections.Generic;
#nullable disable
namespace test.WebApi.Models
{
public partial class Library
{
public Library()
{
GeneratedFiles = new HashSet<GeneratedFile>();
Templates = new HashSet<Template>();
}
public int Id { get; set; }
public long? TenantId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<GeneratedFile> GeneratedFiles { get; set; }
public virtual ICollection<Template> Templates { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace test.WebApi.Dto
{
public class Library
{
public int Id { get; set; }
public long TenantId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
packages and info
AutoMapper 10.1.1
AutoMapper.Extensions.Microsoft.DependencyInjection 8.1.1
.net core 5.0
Here is a whole working demo:
public class HomeController : Controller
{
private readonly IMapper mapper;
public HomeController(IMapper mapper)
{
this.mapper = mapper;
}
public void Index()
{
var item = new test.WebApi.Models.Library()
{
Description = "aa"
};
var library = await Task.FromResult(mapper.Map<test.WebApi.Dto.Library>(item));
}
}
Startup.cs:
services.AddAutoMapper(typeof(CustomMapper));

Code First Entity Framework does not create database with tables

I have Couple of Models (Classes).
City.cs:
public class City
{
[ScaffoldColumn(false)]
public int CityID { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
Course.cs:
public class Course
{
[ScaffoldColumn(false)]
public int ID { get; set; }
public string Faculty { get; set; }
public int CityID { get; set; }
}
CourseDatabaseInitializer.cs:
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace CoursesApplication.Models
{
public class CourseDatabaseInitializer : DropCreateDatabaseAlways<CourseContext>
{
CourseContext _Context = new CourseContext();
protected override void Seed(CourseContext context)
{
GetCities().ForEach(c => context.Cities.Add(c));
}
private static List<City> GetCities()
{
var cities = new List<City> {
new City
{
CityID = 1,
Name = "Paris"
}
};
return cities;
}
public List<Course> GetCourses()
{
return (from c in _Context.Courses select c).ToList();
}
}
}
CourseContext.cs:
using System.Data.Entity;
namespace CoursesApplication.Models
{
public class CourseContext : DbContext
{
public CourseContext(): base("CoursesApplication")
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<City> Cities { get; set; }
}
}
and my Global.asax.cs file :
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Initialize the Courses database.
Database.SetInitializer(new CourseDatabaseInitializer());
}
, but when I run the application, everything is OK. After that in the solution explorer I create connection, but there is no Database with tables. This is my web.config with connection string:
<add name="CourseContext"
connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\courses.mdf;
Integrated Security=True"providerName="System.Data.SqlClient" />
Where can be the problem ?
I am using NET Framework 4.6.1 with Sql Express 2016.
This is ASP.NET WEB Forms project.
In CourseContext Try changing this
public CourseContext(): base("CoursesApplication")
{
}
to this
public CourseContext(): base("CourseContext")
{
}
or remove : base("CoursesApplication")

Many to many relationship returns 0 element collection using entity framework 6

I have a probably simple question, I am trying to create many to many relationships using entity framework and fluent api, and my problem is that when i try to do any query or view a object in debug it has always 0 items.
I am using junction table that looks like:
So relations exists, to be sure ive checked:
select candidate.firstname, skillset.name
from candidate
join candidate_skillset on candidate.id = candidate_skillset.candidate_id
join skillset on candidate_skillset.skillset_id = skillset.id
and joined results are displayed.
Now my context looks like:
public class CatalogContexct : DbContext
{
public DbSet<Candidate> Candidates { get; set; }
public DbSet<SkillSet> SkillSets { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Candidate>().HasMany(t => t.SkillSets).WithMany(t => t.Candidates)
.Map(m =>
{
m.ToTable("candidate_skillset");
m.MapLeftKey("candidate_id");
m.MapRightKey("skillset_id");
});
modelBuilder.Entity<SkillSet>().ToTable("skillset");
modelBuilder.Entity<Candidate>().ToTable("candidate");
}
}
My left side model candidates:
[Table("candidate")]
public class Candidate
{
public Candidate()
{
this.SkillSets = new HashSet<SkillSet>();
}
[Key]
public int id { get; set; }
[Column("firstname")]
public string Firstname { get; set; }
public int? commendation_id { get; set; }
[ForeignKey("commendation_id")]
public Commendation commendation { get; set; }
public ICollection<SkillSet> SkillSets { get; set; }
}
And my rightside model skillset:
[Table("skillset")]
public class SkillSet : SimpleDictionary
{
public SkillSet()
{
this.Candidates = new HashSet<Candidate>();
}
public virtual ICollection<Candidate> Candidates { get; set; }
}
and that model has a parent class:
public class SimpleDictionary
{
[Key]
public int id { get; set; }
[Column("name")]
public string Name { get; set; }
}
So all should work but when I do for example:
var ca = this._catalog.Candidates
.Include("SkillSets").Include("commendation").
FirstOrDefault(x => x.SkillSets.Any());
Result is null, also when I view object on debug collection of property skillset allays has 0 elements, any idea what could be wrong with it?
I tried this with same structure mentioned here in you question and tried locally . And I am able to get the data with this code . Please try this and let me know if this helps . I just omitted commendation table for simplicity .
var context = new SampleDbContext();
var candidates = context.Candidates
.Include("SkillSets").ToList();
foreach (var candidate in candidates)
{
foreach (var sk in candidate.SkillSets.Where( s1 => s1.Candidates.Count(c=>c.id == candidate.id)>0 ))
{
Console.WriteLine( string.Format(#" Name : {0} Skill :{1}",candidate.Firstname ,sk.Name ) );
}
}
Below is my DbContext and Other Entity Classes
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
public class SampleDbContext : DbContext
{
public SampleDbContext()
: base("name=SampleDBConnection")
{
this.Configuration.LazyLoadingEnabled = false;
}
public DbSet<Candidate> Candidates { get; set; }
public DbSet<SkillSet> SkillSets { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Candidate>().HasMany(t => t.SkillSets).WithMany(t => t.Candidates)
.Map(m =>
{
m.ToTable("candidate_skillset");
m.MapLeftKey("candidate_id");
m.MapRightKey("skillset_id");
});
modelBuilder.Entity<SkillSet>().ToTable("skillset");
modelBuilder.Entity<Candidate>().ToTable("candidate");
}
}
[Table("candidate")]
public class Candidate
{
public Candidate()
{
this.SkillSets = new HashSet<SkillSet>();
}
[Key]
public int id { get; set; }
[Column("firstname")]
public string Firstname { get; set; }
public int? commendation_id { get; set; }
//[ForeignKey("commendation_id")]
//public Commendation commendation { get; set; }
public ICollection<SkillSet> SkillSets { get; set; }
}
public class SimpleDictionary
{
[Key]
public int id { get; set; }
[Column("name")]
public string Name { get; set; }
}
[Table("skillset")]
public class SkillSet : SimpleDictionary
{
public SkillSet()
{
this.Candidates = new HashSet<Candidate>();
}
public virtual ICollection<Candidate> Candidates { get; set; }
}
}
The output of the query you mentioned and the result of my code both matched I hope this is that you wanted .

How to rewrite from Raw SQL to LINQ?

I would like to replace my Raw SQL with LINQ. Here's my code:
MyController:
using MyProject.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace MyProject.Controllers
{
public class MyController : ApiController
{
[HttpGet]
public List<User> UserData()
{
var selUserData = "SELECT * FROM mydb.User";
using (var ctx = new ApplicationDbContext())
{
var userData = ctx.Database.SqlQuery<User>(selUserData).ToList();
return userData;
}
}
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
}
}
Web.config:
<connectionStrings>
<add name="MyEntities" providerName="MySql.Data.MySqlClient" connectionString="server=127.0.0.1;port=3306;database=,mydb;uid=root;password=mypass" />
</connectionStrings>
ApplicationDBContext.cs:
using MySql.Data.Entity;
using System.Data.Entity;
namespace MyProject.Models
{
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext() : base(nameOrConnectionString: "MyEntities") { }
}
}
I've been searching the web for some days trying to find a solution, but no luck. Should my code look like something like var userData = ctx... which is just adding a few lines of LINQ syntax or am I doing it all wrong? I read about LINQ not being fully compatible with MySQL. What would my code look like if I were using MSSQL and what would look like if I were using MySQL?
EDIT:
UserDAL.cs:
public class UserDAL
{
public static List<User> UserData()
{
using (var ctx = new MyEntities())
{
var userData = ctx.Users.ToList();
return userData;
}
}
}
MyModel.Context.cs (autogenerated code):
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public partial class MyEntities : DbContext
{
public SloRideEntities()
: base("name=MyEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Ride> Rides { get; set; }
}
User.cs (autogenerated code):
public partial class User
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public User()
{
this.Rides = new HashSet<Ride>();
}
public long Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Ride> Rides { get; set; }
}
You have to add a DbSet<User> to you context class
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext() : base(nameOrConnectionString: "MyEntities") { }
public virtual DbSet<Users> Users { get; set; }
}
Then you write
var userData = ctx.Users.ToList();
Assuming ApplicationDbContext is the class generated by Entity Framework T4 template based on your entity model (edmx file, database first approach) and you have included your mydb.User in the model - then your ApplicationDbContext class should have a property named User(s) which would be a collection of Users.
So you would have something like below
using (var ctx = new ApplicationDbContext())
{
return ctx.Users.ToList();
}

Data does not get inserted: EF Code First

I have following code to insert data into GiftCouponPayment table and Payment table. This code successfully created a database and these two tables. However there is no data inserted in one table - GiftCouponPayment table. What need to be changed in order to make it working?
CODE
static void Main(string[] args)
{
string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
using (var db = new NerdDinners(connectionstring))
{
var giftCouponPayment = new GiftCouponPayment();
giftCouponPayment.MyID=1;
giftCouponPayment.MyValue=250;
List<IPaymentComponent> comps = new List<IPaymentComponent>();
comps.Add(giftCouponPayment);
var payment = new Payment { PaymentComponents = comps, PaymentID = 1, PayedTime=DateTime.Now };
db.Payments.Add(payment);
int recordsAffected = db.SaveChanges();
}
}
Domain Classes
namespace LijosEF
{
public interface IPaymentComponent
{
int MyID { get; set; }
int MyValue { get; set; }
int GetEffectiveValue();
}
public partial class GiftCouponPayment : IPaymentComponent
{
private int CouponValue;
public int MyID
{
get
{
return this.GiftCouponPaymentID;
}
set
{
this.GiftCouponPaymentID = value;
}
}
public int MyValue
{
get
{
return this.CouponValue;
}
set
{
this.CouponValue = value;
}
}
public int GetEffectiveValue()
{
if (this.GiftCouponPaymentID < 2000)
{
return 0;
}
return this.CouponValue;
}
public int GiftCouponPaymentID { get; set; }
}
public partial class Payment
{
public int PaymentID { get; set; }
public List<IPaymentComponent> PaymentComponents { get; set; }
public DateTime PayedTime { get; set; }
}
//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{
public NerdDinners(string connString): base(connString)
{
}
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public DbSet<GiftCouponPayment> GiftCouponPayments { get; set; }
public DbSet<Payment> Payments { get; set; }
}
}
You cannot use interface in your navigation property - EF doesn't support it. You must declare your payment directly with a class:
public partial class Payment {
public int PaymentID { get; set; }
public List<GiftPaymentComponent> PaymentComponents { get; set; }
public DateTime PayedTime { get; set; }
}
If your Payment can have different PaymentComponents you must use mapped inheritance with abstract base class instead of interface.

Categories

Resources