set navigation property from different schema in entity framework - c#

I'm coding in C# using entity framework 5 and I have a model Voucher that is something like this:
public class Voucher
{
public int Id { get; set; }
public int AppId { get; set; }
public virtual App {get; set;}
public int? TradeMemberId { get; set; }
public int FiscalPeriodId { get; set; }
}
I have configured this model as:
ToTable("Voucher", "acc");
So that it is mapped to:
[acc].[voucher]
my App property is from the same database but in another schema:
[prf].[App]
Now when ef tries to query and fill App navigation property it cannot find it in acc schema.how can i mark this property as prf schema as we do for models?any help is appreciated.

If you proper define schema using data annotation. EF should take care of this, I have done this before and never ran into any issues.
[Table("Voucher", Schema = "acc")]
public class Voucher {...}
and
[Table("App", Schema = "prf")]
public class App{...}

Related

C# LINQ Query Hanging

I'm working to create a c# application, and in a portion of the application; I'm looking to bring in a .csv to a data table; and then basically loop through each row and query a database to see if the data exists.
I'm testing a LINQ query; but I can't seem to get it to run and display anything. I have the following code setup to run below:
I have the database added and the connection tests succesfully; I have the classes setup. I've been following some courses on pluralsight to test; and I'm not sure what exactly I am doing wrong or missing.
Also as a note; the table name is actually ERP.PartTran, and not PartTran, but I wasn't succesful in setting that up for the db context; could that be why?
EDIT: Code added; images removed
public class EpiDB : DbContext
{
public DbSet<Tran> PartTran { get; set; }
}
public class Tran
{
public int TranNum { get; set; }
public string TranReference { get; set; }
public string PartNum { get; set; }
}
private static void QueryPartTran()
{
var db = new EpiDB();
int tranref = 4650374; //lookup number
var query = from Tran in db.PartTran
where Tran.TranNum == tranref
orderby Tran.TranNum
select Tran;
foreach (var Tran in query)
{
Debug.Print(Tran.PartNum);
}
}
If you have an existing database schema, the first thing to avoid soft exceptions is to disable schema creation/migration in EF. By default when EF connects to a database and goes to resolve the schema, if it comes across a table that it cannot resolve, it will create it. The clue I see that might be happening in this case is when you say the table is called [ERP].PartTran. I suspect you may find that your database has a new empty table called [dbo].Tran. (assuming SQL Server)
To disable schema creation:
In your Db Context constructor
public EpiDB()
{
Database.SetInitializer<EpiDB>(null);
}
This may go a long ways to identifying any bad schema assumptions that EF is making by convention. Jim's answer would be along the lines of where I would believe your problem will lie.
Entities should map relatively closely, if not identically to your table. Renaming an entity or properties to differ from the table to clarify it in code is fine, but you need to be sure that when you do this, you give EF enough information about your schema so that it can resolve the table correctly. If your table is named "PartTran" and your DbSet instance is named "PartTran", why would you want to name the entity "Tran" rather than "PartTran"?
If your application schema is "ERP" then you can avoid needing to specify the schema name on each entity by adding the following to your DbContext.OnModelCreating():
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasDefaultSchema("ERP");
// ...
}
Otherwise, if you are using multiple schemas then you will need to explicitly map the schema to use with a [Table] attribute or ToTable("{tableName}", "{SchemaName}") in EntityTypeConfig / modelBuilder config.
Next, ensure that your entity fields match the appropriate fields in the table. You don't need to map every field if you don't need them, but at a minimum you do need to map the Primary Key. On a guess from the PartTran entity, I'm guessing you're either missing something like a PartTranId column, or the PK is a composite key using the PartNum and TranNum columns. If you have a PartTranId or similar PK, add it to the entity along with a [Key] attribute. If the PK is a composite:
public class PartTran
{
[Key, Column(Order = 1)]
public int TranNum { get; set; }
public string TranReference { get; set; }
[Key, Column(Order = 2)]
public string PartNum { get; set; }
}
This should give you a few ideas to check out against your code base... To go further it would help to amend your question to include the related tables and any entities you have tried creating so far. Something like "PartTran" looks like a joining table for a many-to-many relationship between a "Part" table and a "Tran"(saction?) table. If that is the case there are a number of options how you can efficiently wire this up in EF to get the data out the way you want.
Try this:
public class EpiDB : DbContext
{
public DbSet<Tran> PartTran { get; set; }
}
[Table("PartTran", Schema = "ERP")]
public class Tran
{
public int TranNum { get; set; }
public string TranReference { get; set; }
public string PartNum { get; set; }
}
And maybe even:
public class EpiDB : DbContext
{
public DbSet<Tran> PartTran { get; set; }
}
[Table("PartTran", Schema = "ERP")]
public class Tran
{
[Key] // Is this your primary key field?
public int TranNum { get; set; }
public string TranReference { get; set; }
public string PartNum { get; set; }
}

ASP.NET Core 2: What could be the code behind a "many-to-one" relationship in this case?

I'm preparing a project's data structure (code-first) in an ASP .NET Core 2 application, with the help of Entity Framework. This specific relationship I have no experience with: the user has to be able to choose diseases with checkboxes, and we have similar choices: cancer type, dietary, etc..
I have more than two tables like the ones on the picture, which will be referred from the UserKitProperties table. This table should work like a connector table, connects the user entity with other entities.
userid1 | cancertypeid1
userid2 | dietaryid1
userid1 | cancertypeid2
userid3 | dietaryid1
How should this be specified in the code, to support this relationship? I was thinking on doing a base class and maybe refer to that id. And this is the connector class..
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
// this should be used for cancer type, dietary, etc..
public long PropertyID { get; set; }
/* Instead of using two classes' ids, maybe call the base class' id
[ForeignKey("PropertyID")]
public CancerType CancerTypes { get; set; }
[ForeignKey("PropertyID")]
public Dietary Dietaries { get; set; } */
}
Thank you in advance for your suggestions! :)
The following should work:
public class Property
{
public long PropertyId { get; set; }
}
public class CancerType : Property
{
// Your code
}
public class Dietary : Property
{
// Your code
}
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
public long PropertyID { get; set; }
[ForeignKey("PropertyID")]
public Property Property { get; set; }
}
But as this MS doc mentions, setting up such inheritence will use a special Discriminator
column in the base class table, to represent what specific type is stored in a row.
I personally would resort to having nullable fields instead in order to not add more complexity. This doesn't enforce, however, that PatientProperties only has one property, which is a considerable minus:
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
public long? CancerTypeID { get; set; }
[ForeignKey("CancerTypeID")]
public CancerType CancerType { get; set; }
public long? DietaryID { get; set; }
[ForeignKey("DietaryID")]
public Dietary Dietary { get; set; }
}
Instead of thinking about the database layout first, you should think about how you would represent this relationship in code. After all, you are doing a code-first approach.
There are basically two choices you could choose: Either the patient has multiple properties, one for each property type, or there is just a single collection for all properties:
public class Patient
{
// …
// option 1
public CancerType CancerType { get; set; }
public Dietary Dietary { get; set; }
public OtherProperty OtherProperty { get; set; }
// option 2
public IList<PatientProperty> Properties { get; set; }
}
Both of these options have their advantages and disadvantages. While option 1 is very explicit and enforces a single value for every type, it also requires you to have a (class) property for every (patient) property. So if you extend your model later, you will have to adjust your patient model.
Option 2 has the benefit that it can just collect everything. So you can just add properties to your patient without having to modify the model later if you introduce new properties. In addition, it would also directly support multiple selections for a single kind. On the downside, it does not verify anything on its own, so you need business logic to actually enforce your rules.
Moving onto the database, for option 2 you obviously need a link table since that is a many-to-many relationship now. Since you only have a link to the base type PatientProperty but you actually want to talk about the concrete type, you will need some kind of discriminator. Discriminators are basically just a notation to additionally store the kind of object in the database.
When storing data with inheritance, what is commonly done is “table-per-hierarchy”. That means that all types within the hierarchy of the PatientProperty base type will share the same table. A discriminator column is used to specify the type, and additional properties that some property types may have are implemented with nullable columns. This setup works out of the box with Entity Framework and is described in this chapter in the documentation.
The other approach, “table-per-type” is not supported in EF Core, so if you wanted to follow that, you would have to implement it yourself. But in your case, where the property types are mostly very similar, I would actually argue against that and actually keep them in the same table.
For option 1, as long as you only have a single property of each kind assigned to the patient, things are a bit simpler. Since you don’t have many-to-many there, you don’t actually need a link table. You just need to store the id for each linked property type in the patient model, as shown in the above UML. Doing that, you can also keep the property types as separate types that do not share a single table in the database.

Entity Framework Core still picks up old column

I recently delete a column ConversationId from my tables. When I start to debug my service and try to save I am getting an error:
Invalid column name 'ConversationId'.
Code:
public class AstootContext : DbContext
{
public AstootContext(DbContextOptions<AstootContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
public DbSet<ServiceRequest> ServiceRequests { get; set; }
}
And my entity looks like this:
public class ServiceRequest
{
public int Id { get; set; }
public int SenderUserId { get; set; }
public int PriceTypeId { get; set; }
public decimal Price { get; set; }
public bool IsAccepted { get; set; }
public DateTime Created { get; set; }
public int MessageId { get; set; }
}
All references to ConversationId were removed from the code, I've rebuilt, yet I'm still getting this error and I don't understand why.
This is my SQL Server table as you can see there is no ConversationId:
Is there a secret cache that I need to delete or something I have to run to update this?
EF Core is code based ORM, with the most important here being the M - Mapper. It doesn't matter what the actual database structure is, the important is what EF *thinks** it is based on your code model (entity classes and their properties, combined with data annotations, fluent configuration and set of conventions).
So the problem should originate from code. Since you've removed the explicit property, it should be caused by shadow property. And as explained in the documentation link, shadow properties are usually introduced by convention from relationships:
Shadow properties can be created by convention when a relationship is discovered but no foreign key property is found in the dependent entity class. In this case, a shadow foreign key property will be introduced.
The documentation also explains the naming rules applied in different scenarios.
A shadow property called ConversationId can be introduced in a several ways, but according to the provided information, the most likely cause is to have an entity class called Conversation defining one-to-many relationship with ServiceRequest by having a collection type navigation property:
public class Conversation
{
public int Id { get; set; }
// ...
public ICollection<ServiceRequest> ServiceRequests { get; set; }
}
Which according to your comment was indeed the case.
For completeness, here are some other possible scenarios generating such property:
(1) No collection navigation property in Conversation, reference navigation property in ServiceRequest:
public class Conversation
{
public int Id { get; set; }
// ...
}
public class ServiceRequest
{
// ...
public Conversation Conversation { get; set; }
}
(2) No navigation properties in Conversation and ServiceRequest, fluent configuration:
modelBuilder.Entity<Conversation>()
.HasMany<ServiceRequest>();
or
modelBuilder.Entity<ServiceRequest>()
.HasOne<Conversation>();
or variations of the above.
(3) No relationship involved, shadow property created through fluent configuration:
modelBuilder.Entity<ServiceRequest>()
.Property<int>("ConversationId");

NHibernate tries to create indexes for a view

I'm writing a C# application that uses NHibernate to access the database. One of my data sources is a view (not a table) named content_profile. I have created the following sample class using NHibernate Attributes:
[Class(Table = "content_profile")]
public class ContentProfile
{
[Id(0, TypeType = typeof(int), Name = #"Id"), Generator(2, Class = #"identity"), Column(1, Name = #"Id")]
public virtual int Id { get; set; }
[NotEmpty]
[MinLength(1)]
public virtual string Name { get; set; }
[Property]
public virtual DateTime? CreationDate { get; set; }
[ManyToOne(Lazy = Laziness.False, Column = #"author_id")]
public virtual User Owner { get; set; }
}
When trying to update schema I get the following error:
NHibernate.Tool.hbm2ddl.SchemaUpdate [(null)] - Unsuccessful: alter table public.content_profile add constraint FK280FFEFD6A68A1F9 foreign key (author_id) references public.users
Npgsql.NpgsqlException:
"content_profile" - is not a table
How do I tell NHibernate that it is indeed a view, not a table, and indexes must not be created on schema update?
You can specify that there should not be done any action on the schema of a certain class map by adding SchemaAction.None, never really used attributes because it lacks features but it should have something like [Class(SchemaAction="None")]

Filling Foreign Key Object in Entity Framework 4

I am using EntityFramework for the first time and maybe this question is so simple...I've used code first method..I have a Class Personnel which looks like this:
public class Personnel
{
public string Id { set; get; }
public int Code { set; get; }
public string Name { set; get; }
public int Type { set; get; }
public JobTitle Title { set; get; }
}
and the JobTitle class:
public class JobTitle
{
public string Id { set; get; }
public int Number { set; get; }
public string Title { set; get; }
public List<Personnel> Personnels { set; get; }
}
which the last property in Personnel Class is a foreign key in personnel table of course..my problem is when I want to retrieve all personnels ( or a personnel ) from DB using lambda expression..the foreign key object is null..the lambda expression is like below:
Context.ContextInstance.Personnels.ToList();
and if I change the expression to this the foreign key object is not null any more.
Context.ContextInstance.Personnels.Include("Title").ToList();
is it the right way??..is there any better way??..I supposed that EF will automatically understand that!!!!..if there are more than 1 FK then I have to use Include for all of them?? please help me to understand.
Thanks
This is due to lazy loading. When you call Context.ContextInstance.Personnels.ToList(); this will fetch all personnel's but Title will not fetch until it get instanced, so make it virtual to get it.
or, you can disable lazy loading by
public MyEntitiesContext() : base("name=MyEntitiesContext", "MyEntitiesContext") {
this.Configuration.LazyLoadingEnabled = false;
}
Doing this will get all related data from context. Using "include" is loading on demand, when you specify properties you want to query.
Virtual keyword allows entity framework runtime create dynamic proxies for your entity classes and their properties, and by that support lazy loading. Without virtual, lazy loading will not be supported, and you get null on collection properties.
If your JobTitle property would be defined as virtual, you wouldn't need to use include.
It's really good explained here: Entity Framework 4.1 Virtual Properties

Categories

Resources