I have these two objects:
public class BaseModule
{
public long BaseModuleID { get; set; }
public string ModuleName { get; set; }
public bool CanOpen { get; set; }
public bool CanConfigure { get; set; }
}
public class ActiveModule
{
public long ActiveModuleID { get; set; }
public long BaseModuleID { get; set; }
public BaseModule Module { get; set; }
}
The BaseModule is in a 1:1 relation to the ActiveModule object and ActiveModule is a wrapper for BaseModule.
Now I want to save ActiveModule but it says that the column BaseModuleID has no default value for it. But in my object the child BaseModule.
I would know expect that the value of the child will be chosen to insert into the column.
Am I missing anything here or just dont really understand how cascading is done in Dapper?
You need the foreign key attribute I think:
public class ActiveModule
{
public long ActiveModuleID { get; set; }
[ForeignKey("Module")]
public long BaseModuleID { get; set; }
public BaseModule Module { get; set; }
}
public class BaseModule
{
public long BaseModuleID { get; set; }
public bool CanConfigure { get; set; }
public bool CanOpen { get; set; }
public string ModuleName { get; set; }
}
Related
I have a task which requires me to return all models from a table using inheritance (TPH).
I have a model class called WorkflowInstance and a derived class CustomWorkflowInstance (which has a string property). There is a discriminator of course.
I want to know of a way where I can return all the elements without considering the discriminator
public class WorkflowInstance : Entity, ITenantScope, ICorrelationScope
{
public WorkflowInstance();
public SimpleStack<ActivityScope> Scopes { get; set; }
public SimpleStack<ScheduledActivity> ScheduledActivities { get; set; }
public WorkflowFault? Fault { get; set; }
public HashSet<BlockingActivity> BlockingActivities { get; set; }
public IDictionary<string, IDictionary<string, object?>> ActivityData { get; set; }
public WorkflowOutputReference? Output { get; set; }
public WorkflowInputReference? Input { get; set; }
public Variables Variables { get; set; }
public Instant? FaultedAt { get; set; }
public Instant? CancelledAt { get; set; }
public Instant? FinishedAt { get; set; }
public Instant? LastExecutedAt { get; set; }
public Instant CreatedAt { get; set; }
public string? Name { get; set; }
public string? ContextId { get; set; }
public string? ContextType { get; set; }
public string CorrelationId { get; set; }
public WorkflowStatus WorkflowStatus { get; set; }
public int Version { get; set; }
public string? TenantId { get; set; }
public string DefinitionId { get; set; }
public ScheduledActivity? CurrentActivity { get; set; }
public string? LastExecutedActivityId { get; set; }
}
public class CustomWorkflowInstance : WorkflowInstance
{
public Guid UserId { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<WorkflowInstance>()
.HasDiscriminator<int>("Discriminator")
.HasValue(0)
.HasValue<WorkflowInstance>(0)
.HasValue<CustomWorkflowInstance>(1);}
I want to find a way to query the table as it is meaning adding where clause FinishedAt > etc (the issue is that UserId exist only in derived class but all the data is in base class where discriminator always equals 0)
so by doing select * from WorkflowInstanceTABLE where Used="xx" it automatically adds the where discriminator = 1 (because I wrote _dbContext.CustomWorkflowInstance which contains the userId in question.
I have the following two classes:
public class Record
{
public int RecordId { get; set; }
public DateTime? InsertDate { get; set; } = DateTime.Now;
public DateTime BookingDate { get; set; }
public string AmountTypeName { get; set; }
public double? Amount { get; set; }
public string BookingAccountID { get; set; }
public string AccountCurrency { get; set; }
public string ClientCurrency { get; set; }
public string AffectsBalance { get; set; }
public double? AmountAccountCurrency { get; set; }
public string AmountClientCurrency { get; set; }
public int UnifiedInstrumentCode { get; set; }
public InstrumentInfo InstrumentInfo { get; set; }
}
public class InstrumentInfo
{
[Key]
public int UnifiedInstrumentCode { get; set; }
public ICollection<Record> Record { get; set; }
public string AssetType { get; set; }
public int UnderlyingInstrumentUic { get; set; }
public string UnderlyingInstrumentSubType { get; set; }
public string InstrumentSymbol { get; set; }
public string InstrumentDescription { get; set; }
public string InstrumentSubType { get; set; }
public string UnderlyingInstrumentAssetType { get; set; }
public string UnderlyingInstrumentDescription { get; set; }
public string UnderlyingInstrumentSymbol { get; set; }
}
that I want to use as my context for EF6.
I defined the context the following way:
public class TransactionsContext: DbContext
{
public DbSet<Record> Records { get; set; }
public DbSet<InstrumentInfo> InstrumentInfos { get; set; }
public TransactionsContext()
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<TransactionsContext>(null);
base.OnModelCreating(modelBuilder);
}
}
If I run a test against it that shall add and InstrumentInfo object to the DB
[TestMethod]
public void AddInstrumentInfo_Added_IsTrue()
{
InstrumentInfo info = FakeFactory.GetInstrumentInfo();
using (var ctx = new TransactionsContext())
{
ctx.InstrumentInfos.Add(info);
ctx.SaveChanges();
}
}
I get the following exception:
SqlException: Cannot insert the value NULL into column
'UnifiedInstrumentCode', table
'TransactionsContext.dbo.InstrumentInfoes'; column does not allow
nulls. INSERT fails. The statement has been terminated.
I tried all different scenarios that I found here but I couldn't figure out what I'm doing wrong.
The ultimate goal is that i define my two classes in a way so that a "Record" is linked to the "InstrumentInfo" table via the "UnifiedInstrumentCode" property.
My guess is that my constraints for this two tables are still not correct, but I cant figure out how to define it in EF6 (code first) to get this working.
Adding the annotation [DatabaseGenerated(DatabaseGeneratedOption.None)] to my primary key in InstrumentInfo solved the problem:
public class InstrumentInfo
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UnifiedInstrumentCode { get; set; }
public ICollection<Record> Record { get; set; }
public string AssetType { get; set; }
public int UnderlyingInstrumentUic { get; set; }
public string UnderlyingInstrumentSubType { get; set; }
public string InstrumentSymbol { get; set; }
public string InstrumentDescription { get; set; }
public string InstrumentSubType { get; set; }
public string UnderlyingInstrumentAssetType { get; set; }
public string UnderlyingInstrumentDescription { get; set; }
public string UnderlyingInstrumentSymbol { get; set; }
}
I did not investigate further but my guess is that if a new Record is added, EF initially creates and InstrumentInfo object that has a Null Value for its Primary key which causes the Exception.
I hope it helps if somebody runs into the same problem in future.
So I created a class using json2csharp
public class ResponseType
{
public class Query
{
public string q { get; set; }
public object sku { get; set; }
public int limit { get; set; }
public object reference { get; set; }
public object mpn_or_sku { get; set; }
public string mpn { get; set; }
public object brand { get; set; }
public string __class__ { get; set; }
public int start { get; set; }
public object seller { get; set; }
}
public class Request
{
public bool exact_only { get; set; }
public string __class__ { get; set; }
public List<Query> queries { get; set; }
}
public class Seller
{
public string display_flag { get; set; }
public bool has_ecommerce { get; set; }
public string name { get; set; }
public string __class__ { get; set; }
public string homepage_url { get; set; }
public string id { get; set; }
public string uid { get; set; }
}
public class Prices
{
public List<List<object>> USD { get; set; }
public List<List<object>> JPY { get; set; }
public List<List<object>> CNY { get; set; }
}
public class Offer
{
public string sku { get; set; }
public string packaging { get; set; }
public string on_order_eta { get; set; }
public string last_updated { get; set; }
public int? order_multiple { get; set; }
public int in_stock_quantity { get; set; }
public string eligible_region { get; set; }
public int? moq { get; set; }
public int? on_order_quantity { get; set; }
public object octopart_rfq_url { get; set; }
public string __class__ { get; set; }
public Seller seller { get; set; }
public string product_url { get; set; }
public object factory_order_multiple { get; set; }
public string _naive_id { get; set; }
public int? factory_lead_days { get; set; }
public Prices prices { get; set; }
public bool is_authorized { get; set; }
public bool is_realtime { get; set; }
}
public class Brand
{
public string homepage_url { get; set; }
public string __class__ { get; set; }
public string name { get; set; }
public string uid { get; set; }
}
public class Manufacturer
{
public string homepage_url { get; set; }
public string __class__ { get; set; }
public string name { get; set; }
public string uid { get; set; }
}
public class Item
{
public List<Offer> offers { get; set; }
public string uid { get; set; }
public string mpn { get; set; }
public List<object> redirected_uids { get; set; }
public Brand brand { get; set; }
public string octopart_url { get; set; }
public string __class__ { get; set; }
public Manufacturer manufacturer { get; set; }
}
public class Result
{
public List<Item> items { get; set; }
public int hits { get; set; }
public string __class__ { get; set; }
public object reference { get; set; }
public object error { get; set; }
}
public class RootObject
{
public int msec { get; set; }
public Request request { get; set; }
public string __class__ { get; set; }
public List<Result> results { get; set; }
}
}
The problem is at design-time, when I declare a variable with the type of my class:
ResponseType Response = new ResponseType();
Intellisense does not allow me to access the subclasses RootObject.results list. It only shows Equals, GetHashCode, GetType and ToString. I am assuming I did something wrong in my class declaration.
Thank you in advance!
Edit -- I am fairly new to C Sharp. I am trying to parse a response from a REST API. I took the JSON provided by the Rest API and converted it using json2csharp into a class. My intent was to do something like this
Within a function return:
public ResponseType ExecuteSearch(String PartNumber)
{
~ ALL CODE FOR GENERATING req
// Perform the search and obtain results
var data = client.Execute(req).Content;
JSON = data;
return JsonConvert.DeserializeObject<ResponseType>(data);
}
Then being able to access the response as an object outside of the function
Edit 2:
I figured out what I did. Instead of nesting everything within the ResponseType I should have simply renamed RootObject to ResponseType.
Intellisense does not allow me to access the subclasses RootObject.results list
it is because the property results is not static and you try to acces it this way. A static property is accessed via ClassName.PropertyName. For more information on static variables check the link.
It only shows Equals, GetHashCode, GetType and ToString
This is the basic set of methods that every object in C# inherits from the class object. This is why you can see it.
Intellisense will allow you to do this:
ResponseType.RootObject ro = new ResponseType.RootObject();
ro.results.First();
because you will need an Instance of that class to acces the property results.
I am assuming I did something wrong in my class declaration.
It depends. Basically if the compiler does not complain then you declared your classes as supposed to be. But the declaration of the properties commands you to access them in a specific way. So if you still want to access results with RootObject.results you need to make it static:
public class RootObject
{
public static List<Result> results { get; set; }
}
But note that this list will exist only once! and is not individual to each instance of RootObject! Since you have embedded classes you need to call it like this:
ResponseType.RootObject.results.WhatEver();
EDIT
I guess you would like to get the Object of type RootObject inside the Object of type ResponseType. If I am right then it is not necessary to declare the classes inside ResponseType but you have to declare variables of each type inside it like:
public class ResponseType
{
public RootObject MyRootObject{ get; set; }
}
public class RootObject
{
public int msec { get; set; }
public Request request { get; set; }
public string __class__ { get; set; }
public List<Result> results { get; set; }
}
Now you will be able to access the results variable inside the ResponseType object:
ResponseType rt = new ResponseType();
rt.MyRootObject.results.WhatEver();
For more information on how to deserialize JSON to classes please read the Deserialize JSON to C# Classes post
1) Object with ResponseType class isn't contain any fields(event static one).
2) You declare ResponseType object, but results is field of RootObject object.
So if you want to work with results you should do something like this:
ResponseType.RootObject rootObject = new ResponseType.RootObject();
rootObject.results.DoWork();
Below is what I think you are trying to do. I would only use it in this form if this is some kind of Data Transfer Object (DTO) because otherwise it is pretty bad practice for a class that would be used in code (mostly because of the public getters and setters on all of the fields and the field names matching the class name), but it does show your main mistake and that is that classes need to be defined outside of your main class and if you need that type of class in your top level class you need to define a public field to access it.
public class ResponseType
{
public Query Query { get; set; }
public Request Request { get; set; }
public Seller Seller { get; set; }
public Prices Prices { get; set; }
public Offer Offer { get; set; }
public Brand Brand { get; set; }
public Manufacturer Manufacturer { get; set; }
public Item Item { get; set; }
public Result Result { get; set; }
public RootObject RootObject { get; set; }
}
public class Query
{
public string q { get; set; }
public object sku { get; set; }
public int limit { get; set; }
public object reference { get; set; }
public object mpn_or_sku { get; set; }
public string mpn { get; set; }
public object brand { get; set; }
public string __class__ { get; set; }
public int start { get; set; }
public object seller { get; set; }
}
public class Request
{
public bool exact_only { get; set; }
public string __class__ { get; set; }
public List<Query> queries { get; set; }
}
public class Seller
{
public string display_flag { get; set; }
public bool has_ecommerce { get; set; }
public string name { get; set; }
public string __class__ { get; set; }
public string homepage_url { get; set; }
public string id { get; set; }
public string uid { get; set; }
}
public class Prices
{
public List<List<object>> USD { get; set; }
public List<List<object>> JPY { get; set; }
public List<List<object>> CNY { get; set; }
}
public class Offer
{
public string sku { get; set; }
public string packaging { get; set; }
public string on_order_eta { get; set; }
public string last_updated { get; set; }
public int? order_multiple { get; set; }
public int in_stock_quantity { get; set; }
public string eligible_region { get; set; }
public int? moq { get; set; }
public int? on_order_quantity { get; set; }
public object octopart_rfq_url { get; set; }
public string __class__ { get; set; }
public Seller seller { get; set; }
public string product_url { get; set; }
public object factory_order_multiple { get; set; }
public string _naive_id { get; set; }
public int? factory_lead_days { get; set; }
public Prices prices { get; set; }
public bool is_authorized { get; set; }
public bool is_realtime { get; set; }
}
public class Brand
{
public string homepage_url { get; set; }
public string __class__ { get; set; }
public string name { get; set; }
public string uid { get; set; }
}
public class Manufacturer
{
public string homepage_url { get; set; }
public string __class__ { get; set; }
public string name { get; set; }
public string uid { get; set; }
}
public class Item
{
public List<Offer> offers { get; set; }
public string uid { get; set; }
public string mpn { get; set; }
public List<object> redirected_uids { get; set; }
public Brand brand { get; set; }
public string octopart_url { get; set; }
public string __class__ { get; set; }
public Manufacturer manufacturer { get; set; }
}
public class Result
{
public List<Item> items { get; set; }
public int hits { get; set; }
public string __class__ { get; set; }
public object reference { get; set; }
public object error { get; set; }
}
public class RootObject
{
public int msec { get; set; }
public Request request { get; set; }
public string __class__ { get; set; }
public List<Result> results { get; set; }
}
I've got a little problem with my database design in an EntityFramework6 project. These are my two code first classes I use to create the database with. As you can see the Details class violates all normal forms out there and I want to split it up properly, however I have no idea how to do it properly, since I am totally new to SQLServer and EF.
So what is the best way to get a decent database design which I then could query?
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationsDetailsDataContract Details { get; set; }
}
internal class LocationDetailsDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }
public string Planet { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
public string System { get; set; }
public string Sector { get; set; }
public LocationDataContract Location { get; set; }
}
Updated Question below
So following the advice of George I did the following. Would this be a decent solution. I Have to add, that I need to to some converting since the application uses different (completely inheritance based) models, which I have to use since a database is not the only source of data and said data uses yet another format to store data which I can't change.
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationsDetails Details { get; set; }
}
internal abstract class LocationDetailDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }}
public LocationsDetails Details { get; set; }
}
internal class CityDetailDataContract : LocationDetailDataContract
{
public string Planet { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
}
internal class PlantDetailDataContract : LocationDetailDataContract
{
public int Population { get; set; }
public string System { get; set; }
}
internal class SystemDetailDataContract : LocationDetailDataContract
{
public string Sector { get; set; }
}
internal class SectorDetailDataContract : LocationDetailDataContract
{
// For now nothing
}
#Ruhrpottpatriot, why all classe are inheriting from LocationDetailDataContract?
Doing this i believe you will have a buch of classes and tables but the data will remain desnormalized (ex: CityDetailDataContract will have the column Planet with repeated strings.
Are you allowed to do something like this from you original question?
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationDetailsDataContract Details { get; set; }
}
internal class LocationDetailsDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }
public Planet Planet { get; set; }
public System System { get; set; }
public Sector Sector { get; set; }
[Required]
public LocationDataContract Location { get; set; }
}
internal class Planet {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
}
internal class System {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
internal class Sector {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
Requirement is to show the parent and child relationship in a nice view. Class is as follows.
public class SearchData
{
public string FieldName { get; set; }
public string Description { get; set; }
public SearchDataType Type { get; set; }
public string Validator { get; set; }
public object DefaultValue { get; set; }
public object SelectedValue { get; set; }
public Dictionary<string, object> ComboBoxItemSource
{
get;
set;
}
public int DefaultSelectedIndex { get; set; }
public bool IsYesOrNo { get; set; }
public OnValidateText OnValidate { get; set; }
public SearchData OptionalElement { get; set; }
public SearchData DependentElement { get; set; }
public bool IsDisplayed { get; set; }
public bool HasValue { get; set; }
}
If DependentElement is not null, UI should have a parent with this dependent element. I think this can be done using hierarchial data template. Can anyone give ideas how should i bind it?
you can use Composite Pattern to design the layout for this.