How To Use Entity Data Model In Class Library - c#

I was successfully able to save data to the Sql Server database, using an Entity Data Model, as follows:
MEDIANEntities db = new MEDIANEntities();
tblCountry objTable = new tblCountry();
objTable.Name= txtName.Text.Trim();
objTable.CreatedDate = System.DateTime.Now;
db.AddTotblCountries(objTable);
db.SaveChanges();
The idea now, is to use the EDM in a class library, so that it can be consumed in other projects (a tier architecture basically). I have created a Class library - 'MedianContext' and then created a new edmx file inside it - 'MedianModel'. And then another class library - 'MedianDAL'. Added the reference of MedianContext to it.
Unable to access properties of objcontext and tb. How can I proceed further.
If it helps, when adding the reference to MedianDAL, the MediaContext.dll was inside the debug folder instead of Release folder, as seen in many examples.

Have you tried it with Linq2Entities?
e.g.:
try
{
using (var medianEntities = new MedianModel.MEDIANEntities())
{
//Do any LinqToEntity-Expressions
}
}
catch(Exception)
{
//ErrorHandling
}
That works for me.
I also have my .edmx files in a different project and just added a reference to this.
Edit:
Of course you have to put this code into a method-body.
Here is a simple example:
public List<Map> GetAllMaps()
{
var Maps = new System.Collections.Generic.List<Map>();
try
{
using (var mapEntities = new Model.MapEntities())
{
var MyMaps= (from M in mapEntities.Maps
orderby M.Description
select M.MapID, M.Description);
foreach (var Map in MyMaps)
{
Maps.Add(Map);
}
}
return Maps;
}
catch (System.Exception Exc)
{
Log.Err(string.Format("Error: {0}", Exc));
throw new System.Exception(Exc.ToString());
}
}

Probably because you are trying to access the properties while in the context of the class ? Create constructor for this class and access the properties from there:
public Test
{
tb....
}

Related

Add/Insert data using repository MVC

I am currently being taught how to use MVC and my supervisor showed me how to use a repository with a read function but I'm stuck with implementing an Add function. This is my current code, thanks in advance!
Repository:
public void AddDriver(DriverModel model)
{
using (var db = new VehicleReservationEntities())
{
var newDriver = new Driver();
newDriver.DriverLastName = model.DriverLastName;
newDriver.DriverFirstName = model.DriverFirstName;
newDriver.DriverLicense = model.DriverLicense;
newDriver.LicenseExpiry = model.LicenseExpiry;
newDriver.MobileNumber = model.MobileNumber;
newDriver.BusinessUnit = model.BusinessUnit;
newDriver.DateRegistered = model.DateRegistered;
db.Driver.Add(newDriver);
db.SaveChanges();
}
}
Controller:
public ActionResult Add()
{
var repo = new VehicleRepository();
var data = repo.AddDriver();
var DVM = new DriverViewModel();
DVM.DriverLastName = data.DriverLastName;
DVM.DriverFirstName = data.DriverFirstName;
DVM.DriverLicense = data.DriverLicense;
DVM.LicenseExpiry = data.LicenseExpiry;
DVM.MobileNumber = data.MobileNumber;
DVM.BusinessUnit = data.BusinessUnit;
DVM.DateRegistered = data.DateRegistered;
db.Driver.Add();
db.SaveChanges();
}
There seems to be a few issues with what you've posted. I think you're looking for something like the following:
Controller:
[HttpPost]
public ActonResult Add(DriverViewModel DVM)
{
var repo = new VehicleRepository();
var driver = new Driver();
//tools such as automapper or tinymapper are often used so that you dont
//need to manually make these assignments
driver.DriverLastName = DVM.DriverLastName;
driver.DriverFirstName = DVM.DriverFirstName;
driver.DriverLicense = DVM.DriverLicense;
driver.LicenseExpiry = DVM.LicenseExpiry;
driver.MobileNumber = DVM.MobileNumber;
driver.BusinessUnit = DVM.BusinessUnit;
driver.DateRegistered = DVM.DateRegistered;
repo.AddDriver(driver);
//return whatever view you want to go to after the save
return View("Index");
}
Repository:
public void AddDriver(Driver newDriver)
{
using (var db = new VehicleReservationEntities())
{
db.Driver.Add(newDriver);
db.SaveChanges();
}
}
a few notes: normally, if you're using viewmodels then these viewmodels are posted to the controller instead of the raw EF entities. You were also calling db.SaveChanges in the controller as well as the repository which doesn't seem like what you want. DbSets are also normally pluralized so your call to add the driver to the db would look like db.Drivers.Add(newDriver). You've also shown 3 different classes related to Drivers: Driver, DriverModel and DriverViewModel. Sometimes this is necessary if your architecture has things separated out into multiple different layers for data access, business logic, and web however I don't see any evidence of that here. If everything exists in one project, I'd probably stick to DriverViewModel and Driver where Driver is the EF entity and DriverViewModel is what your views use and pass back to the controller

C# SubmitChanges dont work

I'm trying to make a database. I made a form and I want to get the data from that. Everything seems okay, but my database didn't get the update and didn't change. I'm using a local database. I tried to change "Copy to output directory" but nothing happened... The SubmitChanges seems ok: I get the Message, but after the program is closed the database doesn't contain the new data... I saw a lot of posts with similar problems, but I didn't find a solution.
My Code:
private void felvetButton_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
if (f2.ShowDialog() == DialogResult.OK)
{
Match m = new Match();
try
{
m.datum = f2.datumTextBox.Text;
m.mod_fk = Convert.ToInt32(f2.modTextBox.Text);
m.acc_fk = Convert.ToInt32(f2.accTextBox.Text);
m.champion = f2.champTextBox.Text;
m.szerep_fk = Convert.ToInt32(f2.roleTextBox.Text);
m.kimenet = f2.resultTextBox.Text;
m.mhossz = f2.lengthTextBox.Text;
m.kill = Convert.ToInt32(f2.killTextBox.Text);
m.death = Convert.ToInt32(f2.deathTextBox.Text);
m.assist = Convert.ToInt32(f2.assistTextBox.Text);
m.kda = float.Parse(f2.kdaTextBox.Text);
m.killpart = float.Parse(f2.kpTextBox.Text);
m.farm = Convert.ToInt32(f2.farmTextBox.Text);
m.ward = Convert.ToInt32(f2.wardTextBox.Text);
m.redward = Convert.ToInt32(f2.redwTextBox.Text);
db.SubmitChanges();
MessageBox.Show("New match added to the database!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Don't you have to make the entity layer aware of this new object? I imagine you need to call something like this for new entities:
db.Matches.InsertOnSubmit(match);
Its perfectly fine to load entities from the database via this entity layer, modify them, and then use db.SubmitChanges() because the entity layer already knows about existing objects! How is it supposed to know about this new object if the entity layer doesn't have any reference to it?

Gridlookupedit Entity Framework

how can i fill the gridlookupedit correctly?.
I can not find the error.
Method fill gridlookupedit
public void CargaGLEVerdadero()
{
pcbjEntidades contexto = new pcbjEntidades();
IList consultaModeloInsumosVerdadera = (from ModeloInsumoes in contexto.ModeloInsumoes
where
ModeloInsumoes.Activo == true
select new
{
ModeloInsumoes.NombreModeloInsumo
}).ToList();
gleNombreModelo.Properties.DataSource = new BindingSource(consultaModeloInsumosVerdadera, "");
}
Construct of form
public frmAgregarMarca()
{
InitializeComponent();
CargaGLEVerdadero();
}
This issue does not related to GridLookup directly rather the to the EF/Winforms interoperation.
Since you are using DevExpress, you can use the Data Source Configuration Wizard.This feature is available for any data-aware control in threir suite and it knows how to do the things correctly and it can make all the work for you:
// This line of code is generated by Data Source Configuration Wizard
// Instantiate a new DBContext
WindowsFormsApplication2.CountriesDBEntities dbContext = new WindowsFormsApplication2.CountriesDBEntities();
// Call the Load method to get the data for the given DbSet from the database.
dbContext.Countries.Load();
// This line of code is generated by Data Source Configuration Wizard
gridLookUpEdit1.Properties.DataSource = dbContext.Countries.Local.ToBindingList();
Then you can customize Wizard's output:
dbContext.Countries.Where(c => c.Capital.StartsWith("A")).Load();

NRefactory: How do I access unresolved Named Arguments on a Property Attribute?

I apologize in advance for the long description of a simple question but I want to make sure people properly understand what I'm trying to do.
Background
I'm writing a tool that can read in a file generated by SqlMetal and create a class that contains methods for simple Inserting, Updating, Deleting and Selecting, which can then be exposed to a web service. The main advantage here is that if a table changes, I simply have to re-run the tool and the database-related code is automatically updated and everywhere that uses it will generate compile errors, making it easy to track down where manual changes need to be made. For example, if I have a Customer table that has the following fields:
CustomerId (PK, Identity)
FirstName
LastName
I want to be able to generate Insert and Delete methods as follows:
// I only want non-database-generated fields to be parameters here.
public static Customer InsertCustomer(String firstName, String lastName)
{
...
}
// I only want the primary key fields to be parameters here.
public static int DeleteCustomer(int customerId)
{
...
}
I am using SqlMetal to generate a Customer class. Now what I want to do is read that .cs file into my new tool in order to create another class with the above methods. This new class can then be exposed to the web service to grant access to this functionality without having to expose the underlying database. I am using NRefactory to read in the SqlMetal-generated file and so far, it's going well but I've run into a snag trying to read the property attributes on my Customer class.
SqlMetal generates its classes using a ColumnAttribute to identify each property that is derived from a database column. The ColumnAttribute will have a number of arguments to describe the database column's properties. In the above example, it would generate something like this:
...
[Column(Name="customerId", Storage="_CustomerId, DbType="INT NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int CustomerId
{
...
}
[Column(Name="firstName", Storage="_FirstName", DbType="NVarChar(100) NOT NULL", CanBeNull=false)]
public String FirstName
{
...
}
[Column(Name="lastName", Storage="_LastName", DbType="NVarChar(100) NOT NULL", CanBeNull=false)]
public String LastName
{
...
}
...
Problem
As you can see, SqlMetal gives me the attributes I need in order to identify which columns are database-generated and which ones are part of the primary key. So when I read this file into NRefactory and resolve the type, I would expect to be able to get at all of this information. However, I'm finding that while I can get to the ColumnAttribute, all of the arguments on it are unresolved and therefore aren't accessible via the NamedArguments or PositionalArguments properties.
Here's my code:
SyntaxTree syntaxTree = ...;
foreach(AstNode tableNode in syntaxTree.Children)
{
ResolveResult result = resolver.Resolve(tableNode);
var properties = result.Type.GetProperties();
foreach (IProperty p in properties)
{
var attributes = p.Attributes;
bool isPrimaryKeyField = false;
bool isDbGenerated = false;
bool isColumn = false;
foreach (IAttribute attr in attributes)
{
if (attr.AttributeType.Name == "Column")
{
isColumn = true;
foreach (var arg in attr.NamedArguments) // NamedArguments contains no items.
{
if (arg.Key.Name == "IsPrimaryKey")
{
isPrimaryKeyField = (bool)arg.Value.ConstantValue == true;
}
if (arg.Key.Name == "IsDbGenerated")
{
isDbGenerated = (bool)arg.Value.ConstantValue == true;
}
}
}
}
if (isColumn)
{
... // Create a parameter as appropriate.
}
}
}
This all works until I try to loop through the IAttribute.NamedArguments because the collection contains no elements. However, when I go through the debugger and examine the value of 'attr', I can see that there is a private variable called 'unresolved', which contains a list of all the arguments I want but I can find no way to access this through code.
How do I get at the contents of this 'unresolved' variable? Do I need to do something more with the Resolver? This is my first time using NRefactory so I'm not overly familiar with all the nuances yet. I've been having a tough time finding an example that goes into this level of depth on Google and the documentation I've seen for NRefactory doesn't seem to cover it. Any help would be appreciated.
I figured it out. I needed to load the assembly for System.Data.Linq into the IProjectContent before resolving the SyntaxTree.
...
CecilLoader loader = new CecilLoader();
Assembly[] assembliesToLoad = {
...
typeof(System.Data.Linq.Mapping.ColumnAttribute).Assembly
...};
IUnresolvedAssembly[] projectAssemblies = new IUnresolvedAssembly[assembliesToLoad.Length];
for(int i = 0; i < assembliesToLoad.Length; i++)
{
projectAssemblies[i] = loader.LoadAssemblyFile(assembliesToLoad[i].Location);
}
IProjectContent project = new CSharpProjectContent();
project = project.AddAssemblyReferences(projectAssemblies);
...

Determining the version of an MSI without installing it

I have an MSI file built from my C# Visual Studio 2010. The version is set through the Version property. I wanted to know if there is a way to determine the version without having to install the file. Currently when right click and view the properties it isn't displayed.
The following code may be helpful. But remember that you should first add a COM reference to the Microsoft Windows Installer Object Library and add the WindowsInstaller namespace to your code. The following function may be what you need.
public static string GetMsiInfo( string msiPath, string Info)
{
string retVal = string.Empty;
Type classType = Type.GetTypeFromProgID( “WindowsInstaller.Installer” );
Object installerObj = Activator.CreateInstance( classType );
Installer installer = installerObj as Installer;
// Open msi file
Database db = installer.OpenDatabase( msiPath, 0 );
// Fetch the property
string sql = String.Format(“SELECT Value FROM Property WHERE Property=’{0}’”, Info);
View view = db.OpenView( sql );
view.Execute( null );
// Read in the record
Record rec = view.Fetch();
if ( rec != null )
retVal = rec.get_StringData( 1 );
return retVal;
}
If you need the version, pass in the name of the MSI file you want, e.g.
string version = GetMsiInfo( "d:\product.msi", “ProductVersion” );
Yes - I think you need to inspect the MSI database however, which requires either some API calls or a wrapper utility.
Microsofts ORCA application should let you do this (although I've never tried it myself).
Instead of using the COM library, you can use the Microsoft.Deployment.WindowsInstaller library from the wixtoolset SDK. Once referenced, you can very similarly get the version info.
private string GetMsiInfo(string msiPath)
{
using (var database = new Microsoft.Deployment.WindowsInstaller.Database(msiPath))
{
var sql = "SELECT Value FROM Property WHERE Property ='ProductVersion'";
using (var view = database.OpenView(sql))
{
view.Execute();
using (var record = view.Fetch())
{
var version = record?.GetString(1);
return version;
}
}
}
}
I haven't found a way to get the correct assembly via nuget installer. However, after I installed the wixtoolset https://wixtoolset.org/releases/, I was able to add a reference in my project directly under assemblies -> extensions -> Microsoft.Deployment.WindowsInstaller.
Based on Gupta's answer, I added COM release calls. If you want to recreate or replace the file you accessed in your further workflow, it might be still in use and you will get an exception if the GC did not yet release the objects, so let's do this manually.
public static string GetMsiInfo(string msiPath, string info)
{
string retVal = string.Empty;
Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
dynamic installer = Activator.CreateInstance(classType);
try
{
// Open msi file
var db = installer.OpenDatabase(msiPath, 0);
try
{
// Fetch the property
string sql = $"SELECT Value FROM Property WHERE Property ='{info}'";
var view = db.OpenView(sql);
try
{
view.Execute(null);
// Read in the record
var rec = view.Fetch();
if (rec != null)
retVal = rec.StringData(1);
return retVal;
}
finally
{
view.Close();
Marshal.ReleaseComObject(view);
}
}
finally
{
//db.Commit();
Marshal.ReleaseComObject(db);
}
}
finally
{
Marshal.ReleaseComObject(installer);
}
}
I think using this code, there is no need to add a COM reference or an extra namespace as mentioned by Gupta, because we use late binding here (see the dynamic).

Categories