I have table called Customer with
CustomerID
Name
Salary etc.
I have added Customer table object to dbml, now on top of Customer table columns I need to add IsProcessed column.
I have added it but it throws exception while retrieving data as "invalid column IsProcessed"
Do i need to create separate POCO object and add extra column
Later fill in the new list with POCO object from db list.
Any alternative solution? Please advise
You can extend class generated from DBML by creating partial class in new file :
public partial class Customer
{
public bool IsProcessed { get; set; }
}
put codes above in new class file and set it's namespace the same as your DBML generated Customer class.
This is common pattern to be able to extend generated class without worrying the extension codes overridden if DBML file regenerated.
[For Reference]
If the models get out of sync with the database and saving the EDMX file and running the “Update Model from Database…” feature doesn’t work, then consider this link
http://blog.jongallant.com/2012/08/entity-framework-manual-update.html#.Uwrul_mSzkA
public class CustomerData
{
public int CustomerID { get; set; }
public string Name { get; set; }
public double Salary { get; set; }
public bool IsProcessed { get; set; }
}
LINQ query:
List<CustomerData> GetData()
{
var data = from cus in context.Customer
select new CustomerData{
CustomerID = cus.CustomerID,
Name = cus.Name,
Salary = cus.Salary
IsProcessed = Your custom field data
};
return data.ToList();
}
Related
I have a table of "Statements" that is related to both :
a table of "Transactions" (with a foreign key on IdStatement)
a table of "SpecificTransactions". The class "SpecificTransaction" inherits from the table "Transaction"
This is the existing code First Model :
Table Statement
[Serializable]
[Table("Statement", Schema = "dbo")]
public class Statement
{
public Statement()
{
this.Transactions = new List<Transaction>();
this.SpecificTransactions = new List<SpecificTransaction>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int IdStatement { get; set; }
public List<Transaction> Transactions { get; set; }
public List<SpecificTransaction> SpecificTransactions { get; set; }
[... Other properties ...]
}
Table Transaction
[Serializable]
[Table("Transaction", Schema = "dbo")]
public class Transaction
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int IdTransaction { get; set; }
[ForeignKey("Statement")]
public Nullable<int> IdStatement { get; set; }
[... Other properties ...]
}
Table SpecificTransaction (inherits from Transaction)
[Serializable]
[Table("SpecificTransaction", Schema = "dbo")]
public class SpecificTransaction : Transaction
{
[StringLength(255)]
public string UniqueValue { get; set; }
[StringLength(50)]
public string Status { get; set; }
[StringLength(50)]
public string Hash { get; set; }
[... Other properties ...]
}
When the database is being created, an unwanted field (i.e column) is added on my table SpecificTransaction, called "Statement_IdStatement".
When I try to add my Statement containing SpecificTransactions, none of the following columns :
Table Transaction > Column IdStatement
Table SpecificTransaction > Column Statement_IdStatement
Is being populated by the IdStatement, I have to add the Id afterwards.
Furthermore, when I assign the "IdStatement" on my table "SpecificTransaction", only the "Statement_IdStatement" column is filled, and not the "IdStatement" of my table Statement.
Is there a way to :
avoid the creation of the column "Statement_IdStatement" and keeping my EF Code First class that way ? (or at least, have no change on the tables Statement and Transaction)
When I add my Statements containing SpecificTransactions and I saveChanges, the column "Transaction" > "IdStatement" is automatically populated ?
Thanks in advance.
You are getting the extra column Statement_IdStatement because you have declared a second relationship, directly between the Statement and SpecificTransaction model types, namely, by the property public List<SpecificTransaction> SpecificTransactions on your Statement class. This is enough to cause Entity Framework to create an extra table column to map that one-to-many relationship to, and that's why it gets filled. It doesn't need to be mapped to an extra foreign-key model property for this to occur.
You probably don't actually need that extra property on Statement. You can actually insert SpecificTransaction objects into the Transactions list property, and the mapping will be taken care of for you.
You may have declared this property in order to be able to access only the SpecificTransaction objects for your Statement. If this was your intent, you can alternatively access them using myStatement.Transactions.OfType<SpecificTransaction>().
When using Entity Framework 6, how is the most efficient way to create an object or objects with additional data from other DbSet entities, when I have a DbContext or IQueryable<T>?
Here is some code:
If I have an Data class as follows:
public class Data
{
[Key]
public int id { get; set; }
public string name { get; set; }
public string data { get; set; }
public int parentId { get; set; }
public int otherDataId { get; set; }
}
And an OtherData class as follows:
public class OtherData
{
[Key]
public int id { get; set; }
public string name { get; set; }
public string data { get; set; }
}
In the Data class, the parentId is a foreign key reference to another Data object in the same DbSet, and the otherDataId is a foreign key reference to an OtherData object in a DbSet<OtherData>.
I would like to get all Data objects in the DbSet<Data>, with the additional DbSet data of the parent Data objects id and name and the OtherData object's id and name. I need this to be in one object to be sent from a webservice GET.
I am not sure on how to do this.
Do I need some code along the lines of:
var result = DbContext.Data.Select(x=> x...).Join(y=> y...) .. new { id = x.id... y.name.. }
Can I please have some help with this code?
You can use a join and project the result. In the below snippet CombinedData is a another class with 2 string fields Name and OtherName. You can also use a view but I think the Join is less work.
IQueryable<CombinedData> result = DbContext.Data.Join(
DbContext.Data.DbContext.OtherData,
outer => outer.OtherDataId,
inner => inner.Id),
(outer, inner) => new { Name = outer.Name, OtherName = inner.Name}
);
Depending on your overall architecture, this may be a good or a bad answer but often when faced with this in the past our teams would create a view in the database to combine the fields. Write your optimized query in the view and then treat it like any other table in your data layer.
You could accomplish the same end result using includes or joins or even writing out the expression in a cross-table query but in my opinion the view is the cleanest and most efficient method.
I am new in breezejs and trying to develop an SPA with angular-breeze.
I have a class named POCOObjectContext which is inherited from the base class ObjectContext. My Database has a table named Customer and as well as I have a POCO named Customer. But I have some extra properties on the POCO Customer, like Email, SupplierName which are not the table columns. When I take the Metadat() from EFContextProvider it provides me only the columns which are in the table named Customer. But the context that holds the POCO named Customer, have all the properties i have declared. As a result in BreezeJS, while creating object from breeze.EntityManager, it is created according to the columns in the Customer Table, but i need these extra properties in the Metadata to get and save data from/to my database. Any help will be highly appreciated...
This is Context Class POCOObjectContext (tmpDataBaseEntities is ConnectionString)
public class POCOObjectContext : ObjectContext
{
private ObjectSet<Customer> customers;
public POCOObjectContext()
: base("name=tmpDataBaseEntities", "tmpDataBaseEntities")
{
customers = CreateObjectSet<Customer>();
}
public ObjectSet<Customer> Customers
{
get { return customers; }
}
}
This is POCO Customer which holds extra properties SupplierName and Email
public class Customer
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string SupplierID { get; set; }
//Extra Properties not in the Customer Table as Columns
public string SupplierName { get; set; }
public string Email { get; set; }
}
Finally the Breeze Controller
[BreezeController]
public class ReceiveServiceController : ApiController
{
EFContextProvider<POCOObjectContext> _pocoContext = new EFContextProvider<POCOObjectContext>();
ReceiveDal _rcvDal = new ReceiveDal();
[HttpGet]
public string Metadata()
{
var t = _pocoContext.Metadata();
return t; // It holds the properties info that match with POCO and Database Table.
}
}
As you have discovered, custom unmapped properties on the server are not included in the metadata definition sent to the client. You can, however, extend your client's Customer definition by doing something like this,
//Assuming you have camelCase naming convention enabled
function Customer() {
this.supplierName = '';
this.email = '';
}
entityManager.metadataStore.registerEntityTypeCtor('Customer', Customer);
Now when you call saveChanges, Breeze will include the above custom properties in the payload.
{"Id": 42, "Name": "Customer Name","__unmapped":{"supplierName":"Supplier Name", "email": "supplier#supplier.com"},...}
Then, on the server, you can examine and parse the JObject payload to retrieve the unmapped properties.
You can read more about extending Breeze entities on the client at http://www.breezejs.com/documentation/extending-entities
Hope this helps.
I am new to asp.net C# and trying to learn by building a simple web app based on MVC 3 Music application. So far i have had a decent run but i am running into this this and i am not able to figure out the root cause. plz help
I am building a simple website where Projects are listed, then clicking on projects you see all the tables and then clicking on table you see all the columns. Projects/Tables/Column are being fetched from SQL db which has valid data and PK/FK keys defined. i am able to navigate from projects to tables and can see all columns under tables but when I click on column link, i get error as described below.
ERROR: "Invalid column name 'Tables_Id'." SQL profiler shows this column in the query but i do not understand where is it coming from as I do not have any such columm.
CONTROLLER CLASS
public class ProjectController : Controller // Inherit from base class Controller
{
DbEntities storeDB = new DbEntities(); //Create Object/instance of class //StorDB is reference to an object
public ActionResult Index()
{
var Name = storeDB.ProjectNM.ToList(); //Use 'var' coz we may have any type returned, 'var' is determined at run time
return View(Name);
}
public ActionResult BrowseTables(string Projects)
{
var ProjectModel = storeDB.ProjectNM.Include ("Tabless")
.Single(g => g.Name == Projects);
return View(ProjectModel);
}
public ActionResult BrowseColumns(string TableIs)
{
var ProjectModel1 = storeDB.TableNM.Include("Columnss")
.Single(g => g.Tbl_Name == TableIs);
return View(ProjectModel1);
//var ColumnModel = storeDB.TableNM.Find(TableIs);
// return View(ColumnModel);
}
}
Other Classes
public partial class Projects //Partial class, see comment below
{
public int Id { get; set; }
public string Name { get; set; }
public List<Tables> Tabless { get; set; } //Navigation Property, required so that we can include tables under projects
}
public class Tables
{
public int Id { get; set; }
public int ProjectId { get; set; }
public string Tbl_Name { get; set; }
public Projects Project { get; set; } //Class table can have (belong) only one project
public List<Columns> Columnss { get; set; } //Table can have more than one column
}
public class Columns
{
public int Id { get; set; }
[ForeignKey("Tables")]
public int TblId { get; set; }
public string Column_Name { get; set; }
public string IncludeFlag { get; set; }
}
View
<ul>
#foreach (var Tables in Model.Tabless)
{
<li>
#Html.ActionLink(Tables.Tbl_Name, "BrowseColumns", new { TableIs = Tables.Tbl_Name })
</li>
}
Query from SQL profiler
[Project2].[Tables_Id] AS [Tables_Id]
As you can seethe query has a column [Tables_Id] and I do nto understand why it is there as i do nto have any such column. Please help!
Basically MVC3 and EF4 do a lot of things on convention.
My suggestion to make things a little clearer for yourself is read up on EF 4.1 a little, and let it pluralize your table names for you, and use the data annotations (or property mapping if you don't like the attributes in your model) to mark your object's Id properties...
This is not necessarily the cause of your problem, but I think you will find it a lot easier to see what is going on in your profiler and models when the names/values make more logical sense.
Start by singularizing your objects: Table, Column, etc. or even using a more descriptive name... again if for no other reason it will be easier for you to read and debug, or even to get better answers here.
The convention for EF4.1 and foreign keys is to name them {TableName}_{ColumnName} so your foreign key to Tables is expecting a column names Table_Id (because Table is the name of the table, and Id is the name of the PK column.
This might help: EF 4.1 messing things up. Has FK naming strategy changed?
I have 2 views in SQL set up:
PurchaseOrder
PurchaseOrderLineItems
These have many columns aliased (the tables they view/join are not sensibly named... it's a 3rd party product)
I have 2 classes (simplified below)
class PurchaseOrder
{
public string PoNumber { get; set; }
public string Vendor { get; set; }
public DateTime DateCreated { get; set; }
public IEnumerable<PurchaseOrderLineItems> LineItems { get; set; }
}
and
class PurchaseOrderLineItems
{
public string PoNumber { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
I'm using Linq to Sql - with XML mapping file (created with help from sqlmetal.exe)
What I want to do is effectivly populate the IEnumerable in PurchaseOrder with records from the PurchaseOrderLineItem view - effectively joining the tables
I wanted to do this using POCO - without having to add EntitySet<> to my class, as eventually, I will change my ORM to something like nHibernate (which has bag attribute i believe...?)
Currently, I've got a stored procedure - sp_getPurchaseOrderLineItems which takes the PONumber, and then returns a list of PurchaseOrderLineItem objects, that i then add to my result set (this is far, far from ideal)
is there any way I can do what i need? So that basically, a query on PurchaseOrder returns an already populated IEnumerable of LineItems within the instance?
It's worth mentioning that this will only ever be read-only, we'll never be inserting / updating data using this.
You can extend your PurchaseOrder class to implement the OnLoadedMethod:
public partial class PurchaseOrder
{
partial void OnLoaded()
{
LineItems = FunctionToCall_sp_getPurchaseOrderLineItems_AndBuildSet();
}
}
This will at least get the line items automatically when you get your PO.
This is the n+1 problem. nHibernate has a solution for this, which is called join-fetch querying. What it basically does is a outer-join query between order and order-line, which will result in the product of the row counts of the two tables.
I don't think Linq2SQL does have a solution for it. But you can still use your stored procedure to generate the join-fetch output, and have some Linq2Objects code to distinct the unique orders and the order-lines out of the result.