Entity Framework With MySql Connectivity not working - c#

I have been wandering around for this but couldn't find a single good article that would work. There are bits and peaces everywhere but not a complete code for this.
It's frustrating why Microsoft would make it so hard to connect EF with MySql whereas for SQL Server it takes only few mins.
Could anyone please make it easier and just illustrate in simple steps to create EF with MySql. I am only interested in the connection part otherwise i have been working in EF for couple of years. I know the rest. Here's the code and the related libraries.
Data Context Class
public ReservationDataContext() : base(#"server=localhost;port=3306;database =xxx;uid=xx;pwd=xx") { }
partial void OnCreated();
public ReservationDataContext(string connectionString): base(connectionString)
{
this.OnCreated();
}
public ReservationDataContext(string connection, MappingSource mappingSource) :
base(connection,mappingSource)
{
this.OnCreated();
}
public Table<Reservation> Reservations
{
get
{
return this.GetTable<Reservation>();
}
}
Entity Class:
[Table(Name = "reservations")]
public class Reservation
{
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int Id { get; set; }
[Column]
public bool IsReserved { get; set; }
[Column]
public string Status { get; set; }
The dlls are as follows.
dlls
I was getting errors where it was picking up sql server entity framework instead of mysql dll. So resolved that. Isn't giving any error on that but returns null and not fetching the data. Here's the code for that.
In Query Handler class.
private ReservationContext reservationContext;
public QueryHandler()
{
reservationContext = new ReservationContext(ConfigurationManager.ConnectionStrings["ReservationDataContext"].ConnectionString);
}
public List<Reservation> GetAllReservations()
{
List<Reservation> resList = reservationContext.Reservations.ToList();
return resList;
}

Related

How do I implement a simple "complex type" in Entity Framework Core 2/C#?

I'm using Entity Framework and .Net Core 2.0 for the first time (I'm also pretty new to C#, but I've been using the traditional .Net Framework & VB since version 1... so I'm no newbie to .Net development), and I've already run into a problem creating my database.
Take this simple scenario: I want to store some information about some electric pumps. Two of the properties are a min/max type range, so I've implemented these as a simple class, thus:
public class Pump
{
[Key]
public int pumpId { get; set; }
public string pumpName { get; set; }
public int pumpControlChannel { get; set; }
public MinMax normalCurrent { get; set; }
public MinMax normalFlowRate { get; set; }
}
[ComplexType]
public class MinMax
{
public int min { get; set; }
public int max { get; set; }
}
As you can see, I've tried the [ComplexType] decorator, to no avail.
Anyway, now create a dead simple DBContext class to manage my Pumps class. I'm using Sqlite:
public class EFDB : DbContext
{
public DbSet<Pump> pumps { get; private set; }
private static DbContextOptions GetOptions(string connectionString)
{
var modelBuilder = new DbContextOptionsBuilder();
return modelBuilder.UseSqlite(connectionString).Options;
}
public EFDB(string connectionString) : base(GetOptions(connectionString)) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
try
{
// modelBuilder.ComplexType<MinMax>(); // ComplexType not recognised
base.OnModelCreating(modelBuilder);
}
catch (Exception ex)
{
System.Diagnostics.Debugger.Break();
}
}
}
and lastly a simple static class to call it (I embeded it in a bigger program... to duplicate this problem you could just stick the code lines into program.cs):
public static class TryMe
{
public static void MakeMeFail()
{
using (var db = new EFDB("FileName=C:\\temp\\test_effail.db"))
{
try
{
db.Database.EnsureCreated();
}
catch (Exception ex)
{
System.Diagnostics.Debugger.Break(); // If we hit this line, it fell over
}
}
System.Diagnostics.Debugger.Break(); // If we hit this line, it worked.
}
}
Just call TryMe.MakeMeFail(), the code fails at db.Database.EnsureCreated().
From everything I've read, [ComplexType] should do what I want... but it Just Doesn't. Nor can I find modelBuilder.ComplexType<T> anywhere.
It may just be a library reference I'm missing...? The above code uses the following:
using System;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
However, NONE of the documentation/examples I can find anywhere show which libraries need referencing!
Thanks in advance.
[PS: Apologies to those who already saw this question, I'm using EF Core 2.0, NOT EF6]
Typical... it's always the way, isn't it? 5 minutes after posting, you discover the answer to your own question....
The answer, in this case, can be found here:
https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities
EF Core calls this sort of entity an "owned" entity, rather than a "complex type".
Simply adding these lines to `OnModelCreating' fixed the issue:
modelBuilder.Entity<Pump>().OwnsOne(p => p.normalCurrent);
modelBuilder.Entity<Pump>().OwnsOne(p => p.normalFlowRate);
The database now creates (correctly, I think, I haven't verified that yet).

Dynamically change a type with C#

I am very new to C# and ServiceStack and I am working on a small project that consists on calling a third party API and loading the data I get back from the API into a relational database via ServiceStack's ORMLite.
The idea is to have each endpoint of the API have a reusable model that determines how it should be received in the API's response, and how it should be inserted into the database.
So I have something like the following:
[Route("/api/{ApiEndpoint}", "POST")]
public class ApiRequest : IReturn<ApiResponse>
{
public Int32 OrderId { get; set; }
public DateTime PurchaseDate { get; set; }
public String ApiEndpoint { get; set; }
}
public class ApiResponse
{
public Endpoint1[] Data { get; set; }
public String ErrorCode { get; set; }
public Int32 ErrorNumber { get; set; }
public String ErrorDesc { get; set; }
}
public class Endpoint1
{
[AutoIncrement]
public Int32 Id { get; set; }
[CustomField("DATETIME2(7)")]
public String PurchaseDate { get; set; }
[CustomField("NVARCHAR(50)")]
public String Customer { get; set; }
[CustomField("NVARCHAR(20)")]
public String PhoneNumber { get; set; }
public Int32 Amount { get; set; }
}
My first class represents the API's request with its route, the second class represents the API's response. The API's response is the same for all endpoints, but the only thing that varies is the structure of the Data field that comes back from that endpoint. I've defined the structure of one of my endpoints in my Endpoint1 class, and I am using it in my API's response class. As you can see, I am also defining a few attributes on my Endpoint1 class to help the ORM make better decisions later when inserting the data.
Ok, so the issue is that I have about 15 endpoints and I don't want to create 15 ApiResponse classes when I know the only thing that changes is that first Data field in the class.
So I made something like this:
public class DataModels
{
public Type getModel(String endpoint)
{
Dictionary<String, Type> models = new Dictionary<String, Type>();
models.Add("Endpoint1", typeof(Endpoint1));
// models.Add("Endpoint2", typeof(Endpoint2));
// models.Add("Endpoint3", typeof(Endpoint3));
// and so forth...
return models[endpoint];
}
}
I would like for getModel() to be called when the request is made so that I can pass in the ApiEndpoint field in the ApiRequest class and store the type that I want my Data field to have so that I can dynamically change it in my ApiResponse class.
In addition, there is the ORM part where I iterate over every endpoint and create a different table using the model/type of each endpoint. Something like this:
endpoints.ForEach(
(endpoint) =>
{
db.CreateTableIfNotExists<Endpoint1>();
// inserting data, doing other work etc
}
);
But again, I'd like to be able to call getModel() in here and with that define the model of the specific endpoint I am iterating on.
I've attempted calling getModel() on both places but I always get errors back like cannot use variable as a typeand others... so I am definitely doing something wrong.
Feel free to suggest a different approach to getModel(). This is just what I came up with but I might be ignoring a much simpler approach.
When I DID understand you correctly, you have different API-Calls which all return the same object. The only difference is, that the field "Data" can have different types.
Then you can simply change the type of data to object:
public object Data { get; set; }
And later simply cast this to the required object:
var data1=(Endpoint1[]) response.Data;
You're going to have a very tough time trying to dynamically create .NET types dynamically which requires advanced usage of Reflection.Emit. It's self-defeating trying to dynamically create Request DTOs with ServiceStack since the client and metadata services needs the concrete Types to be able to call the Service with a Typed API.
I can't really follow your example but my initial approach would be whether you can use a single Service (i.e. instead of trying to dynamically create multiple of them). Likewise with OrmLite if the Schema of the POCOs is the same, it sounds like you would be able to flatten your DataModel and use a single database table.
AutoQuery is an example of a feature which dynamically creates Service Implementations from just a concrete Request DTO, which is effectively the minimum Type you need.
So whilst it's highly recommended to have explict DTOs for each Service you can use inheritance to reuse the common properties, e.g:
[Route("/api/{ApiEndpoint}/1", "POST")]
public ApiRequest1 : ApiRequestBase<Endpoint1> {}
[Route("/api/{ApiEndpoint}/2", "POST")]
public ApiRequest2 : ApiRequestBase<Endpoint1> {}
public abstract class ApiRequestBase<T> : IReturn<ApiResponse<T>>
{
public int OrderId { get; set; }
public DateTime PurchaseDate { get; set; }
public string ApiEndpoint { get; set; }
}
And your Services can return the same generic Response DTO:
public class ApiResponse<T>
{
public T[] Data { get; set; }
public String ErrorCode { get; set; }
public Int32 ErrorNumber { get; set; }
public String ErrorDesc { get; set; }
}
I can't really understand the purpose of what you're trying to do so the API design is going to need modifications to suit your use-case.
You're going to have similar issues with OrmLite which is a Typed code-first POCO ORM where you're going to run into friction trying to use dynamic types which don't exist at Runtime where you'll likely have an easier time executing Dynamic SQL since it's far easier to generate a string than a .NET Type.
With that said GenericTableExpressions.cs shows an example of changing the Table Name that OrmLite saves a POCO to at runtime:
const string tableName = "Entity1";
using (var db = OpenDbConnection())
{
db.DropAndCreateTable<GenericEntity>(tableName);
db.Insert(tableName, new GenericEntity { Id = 1, ColumnA = "A" });
var rows = db.Select(tableName, db.From<GenericEntity>()
.Where(x => x.ColumnA == "A"));
Assert.That(rows.Count, Is.EqualTo(1));
db.Update(tableName, new GenericEntity { ColumnA = "B" },
where: q => q.ColumnA == "A");
rows = db.Select(tableName, db.From<GenericEntity>()
.Where(x => x.ColumnA == "B"));
Assert.That(rows.Count, Is.EqualTo(1));
}
Which uses these extension methods:
public static class GenericTableExtensions
{
static object ExecWithAlias<T>(string table, Func<object> fn)
{
var modelDef = typeof(T).GetModelMetadata();
lock (modelDef)
{
var hold = modelDef.Alias;
try
{
modelDef.Alias = table;
return fn();
}
finally
{
modelDef.Alias = hold;
}
}
}
public static void DropAndCreateTable<T>(this IDbConnection db, string table)
{
ExecWithAlias<T>(table, () => {
db.DropAndCreateTable<T>();
return null;
});
}
public static long Insert<T>(this IDbConnection db, string table, T obj, bool selectIdentity = false)
{
return (long)ExecWithAlias<T>(table, () => db.Insert(obj, selectIdentity));
}
public static List<T> Select<T>(this IDbConnection db, string table, SqlExpression<T> expression)
{
return (List<T>)ExecWithAlias<T>(table, () => db.Select(expression));
}
public static int Update<T>(this IDbConnection db, string table, T item, Expression<Func<T, bool>> where)
{
return (int)ExecWithAlias<T>(table, () => db.Update(item, where));
}
}
But it's not an approach I'd take personally, if I absolutely needed (and I'm struggling to think of a valid use-case outside of table-based Multitenancy or sharding) to save the same schema in multiple tables I'd just be using inheritance again, e.g:
public class Table1 : TableBase {}
public class Table2 : TableBase {}
public class Table3 : TableBase {}

C# WCF - ADO.NET Entity model - DbSet empty?

I created a new WCF project in visual studio based on a existing database.
I made two operations. One operation writes a record (createProfile) to the database and one retrieve data (GetProfiles). My project exists of 3 files: web.config, a edmx file and my svc class.
CreateProfile works fine, I checked in SQL and the record is created.
GetProfiles never gives a response. When I debug the context.UserProfileSet always counts 0 values.
Any suggestions on what is going wrong?
[DataContract]
public partial class UserProfile
{
public int Id { get; set; }
[DataMember]
public string UserName { get; set; }
}
public class MusicOwnerService : IMusicOwnerService
{
IEnumerable<UserProfile> GetProfiles()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
return context.UserProfileSet.AsEnumerable();
}
}
public void CreateProfile()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
context.UserProfileSet.Add(new UserProfile { UserName = "John" });
context.SaveChanges();
}
}
}
As far as I know, you cant pass an IEnumerable object over the wire with WCF (unless youve a duplex binding of some sort??).. so you would be best to convert to a list and return that list like below:
List<UserProfile> GetProfiles()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
return context.UserProfileSet.ToList();
}
}

MVC 4.0 Controller cannot find seeded data

I am attempting to seed data for an MVC 4 project using SQL server 4.0 as the database engine, using the Microsoft MVC music store tutorial as an example. I have set up a seed and DB context models, but the controller is not able to find the data. I have verified that the the database file is created in App_Data and verified that SetIntitializer is correctly set up in Application_Start. Here is what I have for code:
Seed data:
namespace RationalMethodApp.Models
{
public class StartData : CreateDatabaseIfNotExists<RationalMethodEntities>
{
protected override void Seed(RationalMethodEntities context)
{
new List<Basin>
{
new Basin {
basinId = 1, // attempting to force a key value, will remove
Name = "Replace me with a real basin",
Location = "In a real location",
drainageArea = 0.0M
}
}.ForEach(b => context.Basins.Add(b));
Controller:
public ActionResult Index(int? bsnId)
{
if (bsnId == null) // here to force a key value, will change
bsnId = 1;
var basin = rmDb.Basins.Find(bsnId);
return View(basin);
}
The context class is:
namespace RationalMethodApp.Models
{
public class RationalMethodEntities : DbContext
{
public DbSet<Basin> Basins { get; set; }
public DbSet<SubArea> SubAreas { get; set; }
public DbSet<IdfCurve> IdfCurves { get; set; }
public DbSet<Analysis> Analyses { get; set; }
public DbSet<FlowSegment> FlowSegments { get; set; }
public DbSet<SheetFlowN> SheetFlowNs { get; set; }
public DbSet<RunoffCoefficient> RunoffCoefficients { get; set; }
public DbSet<StormFrequency> stormFrequencies { get; set; }
}
}
The debugger tells me that the "basin" object is still null in the controller after the .Find. This must be a simple, basic thing that I have overlooked, but all of the help I can find on-line assumes that the askers know what they are doing - not true in my case! I have also checked the discussion at Entity Framework database seed doesn't seed
but this does not seem to be the answer. Please bear with a total noob question.
You don't show the full code of you seed, so i can't really be sure, but you might be missing the Context.Changes().
As well you wrote
public class StartData : CreateDatabaseIfNotExists<RationalMethodEntities>
If you don't delete your database before the application start, it won't do anything as the db already exists.
You could use :
public class StartData : DropCreateDatabaseAlways <RationalMethodEntities>
to drop it every time you start or
public class StartData : DropCreateDatabaseAlways <DropCreateDatabaseIfModelChanges >
to drop db when Model changes (which is great for start of dev)
To debug: Drop your database, kill your application server (so it goes back to application start), breakpoint in your seed. Start Debug, if it goes in seed, check that data is in it after SaveChange().

Entity Framework Code First, nonempty setter or getter?

I am working with an EF Code First project, and all is well. I have a simple Class, Customer. In my Customer Class I have a field I want to encrypt (Yes, I know I can encrypt at the DB level but requirements dictate I encrypt at the Domain/Code level), so I am hoping that I can do something like the following:
public class Customer
{
public int CustomerID { get; set; }
public string FieldToEncrypt { get; set { _FieldToEncrypt = MyEncryptionFunction.Encrypt(); } }
}
However, I assume that if the setter has a definition, entity framework code first may ignore that property when generating the schema. So my question is, is there a way to do EF Code First with provided getters/setters, or should I move this functionality into a constructor? Should I override one of the methods/events that happens when the Context is saving, instead?
EDIT ********************
As a note, I am using DataService to transmit the data over an OData protocol service. This automatically generates insert/update/select methods. Some of the suggestions require creating a second property, but the DataService class does not seem to pass through NotMapped properties. This throws a bit of a kink into my earlier question.
public class Customer
{
public int CustomerID { get; set; }
public string EncryptedField { get; private set; }
[NotMapped]
public string Field
{
get { return MyEncryptionFunction.Decrypt(EncryptedField); }
set { EncryptedField = MyEncryptionFunction.Encrypt(value); }
}
}

Categories