I have the following code:
public void Remove(Guid id)
{
var symbol = new Symbol()
{
Id = id
};
_ctx.Entry(symbol).State = EntityState.Deleted;
_ctx.SaveChanges();
}
The symbol entity has a related entity called "Category". It is not set up to cascade delete since it is a value from a lookup table. I want to leave the category alone, however when this runs it throws a DbUpdateException:
Entities in 'HourlyContext.Symbols' participate in the 'Symbol_Category' relationship. 0 related 'Symbol_Category_Target' were found. 1 'Symbol_Category_Target' is expected.
I understand that EF is confused about what to do with the relationship, how can I tell it to simply discard the reference to the Category and go ahead and delete the Symbol?
Thanks.
.
EDIT
Okay so I tried making the foreign key nullable (FYI I am using code first Entity Framework) by adding a nullable CategoryId as shown here:
public class Symbol : EntityBase
{
[Required]
public string CompanyName { get; set; }
public int? CategoryId { get; set; }
[Required]
public MarketCategory Category { get; set; }
}
However, after creating a migration and updating the database, this does not resolve the exception.
.
EDIT 2
Okay so it turns out that (looking back now it's obvious) that adding the 'required' attribute prevents the column from being nullable. Now my intention was to not allow the coder (i.e. me) from accidentally setting the relationship to null in code, but allow the framework to null it out when I delete the object via Id. It appears this cannot be done. So all I needed to do was to remove the required attribute (and leave out the 'categoryId' column).
there must be a foreign key relationship being generated by EF. Easy way to check is to use SQL sever managent Studio and check for dependencies on the table
To do so, I think the foreign key column of Category table (SymbolId, whatever ...) Should be Nullable. The OndDelete action of your database table should be set null, too.
Then, EF can simply remove that symbol.
Related
I'm creating an Azure Mobile Service using Entity Framework Code First and trying to follow the [Class]Id naming convention for Keys. My goal is to have the [Class]Id column be the sole Primary Key and not have any Id column created. I can't seem to get that to happen. When I scaffold a new Azure Table Controller from the following, the generated code creates ClientId, but also creates Id. When I test the code I get the error "Unable to determine composite primary key ordering..." because (I assume) I'm not addressing the Column Order of Id since it doesn't even appear in the Class.
public class Client: EntityData
{
// Unique ID of this client (PK)
[Key, Column(Order = 1), Required, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid ClientId { get; set; }
(...)
}
Not sure it's relevant, but note that I am setting the value of ClientId and not asking the db to auto-set it for me.
What have I missed? Thanks!
Your Client class is inheriting from EntityData which already contains a Primary Key called Id
Public class EntityData : ITableData
{
[Key]
[TableColumn(TableColumnType.Id)]
public string Id { get; set; }
//Other system properties
}
You could remove the EntityData and setup your own keys etc but you may run into more problems than its worth with Azure Mobile Services
I’m using Entity Framework 5.0,
Scenario
"Organisation" has a list of "clients" and a list of "Periods" and a "CurrentPeriodID" At the start of each period some or all of the "Clients" are associated with that "Period", this I have done using a link table and this works OK so when I do "Organisation->Period->Clients" I get a list of "Clients" for the "Period".
Next I need to add some objects ("Activities") to the "Clients" for a "Period" so I get "Organisation->Period->Client->Activates" this won’t be the only one there will eventually be several other navigation properties that will need to be added to the "Clients" and the "Activities" and all of them have to be "Period" related, I also will have to be able to do (if possible) "Organisation->Period-Activities".
Question
What would be the best way of implementing the "Activities" for the "Organisation->Period-Client", I Don’t mind what way it is done Code First reverse Engineering etc. Also on the creation of the "Organisation" object could I load a current "Period" object using the "CurrentPeriodID" value which is stored in the "Organisation" object.
Thanks
To me this sounds like you need an additional entity that connects Period, Client and Activity, let's call it ClientActivityInPeriod. This entity - and the corresponding table - would have three foreign keys and three references (and no collections). I would make the primary key of that entity a composition of the three foreign keys because that combination must be unique, I guess. It would look like this (in Code-First style):
public class ClientActivityInPeriod
{
[Key, ForeignKey("Period"), Column(Order = 1)]
public int PeriodId { get; set; }
[Key, ForeignKey("Client"), Column(Order = 2)]
public int ClientId { get; set; }
[Key, ForeignKey("Activity"), Column(Order = 3)]
public int ActivityId { get; set; }
public Period Period { get; set; }
public Client Client { get; set; }
public Activity Activity { get; set; }
}
All three foreign keys are required (because the properties are not nullable).
Period, Client and Activity can have collections refering to this entity (but they don't need to), for example in Period:
public class Period
{
[Key]
public int PeriodId { get; set; }
public ICollection<ClientActivityInPeriod> ClientActivities { get; set; }
}
You can't have navigation properties like a collection of Clients in Period that would contain all clients that have any activities in the given period because it would require to have a foreign key from Client to Period or a many-to-many link table between Client and Period. Foreign key or link table would only be populated if the client has activities in that Period. Neither EF nor database is going to help you with such a business logic. You had to program this and ensure that the relationship is updated correctly if activities are added or removed from the period - which is error prone and a risk for your data consistency.
Instead you would fetch the clients that have activities in a given period 1 by a query, not by a navigation property, for example with:
var clientsWithActivitiesInPeriod1 = context.Periods
.Where(p => p.PeriodId == 1)
.SelectMany(p => p.ClientActivities.Select(ca => ca.Client))
.Distinct()
.ToList();
I have the following Domain Model:
public class DaybookEnquiry : Entity
{
public DateTime EnquiryDate { get; set; }
[ForeignKey("EnquiryType")]
public int DaybookEnquiryTypeId { get; set; }
public string AccountNumber { get; set; }
[ForeignKey("User")]
public int UserId { get; set; }
#region Navigation Properties
public virtual User User { get; set; }
public virtual DaybookEnquiryType EnquiryType { get; set; }
public virtual ICollection<DaybookQuoteLine> QuoteLines { get; set; }
#endregion
}
This is inside of a project named DomainModel. Entity is just a base class which my domain models inherit from, it contains an Id field.
I then have other projects inside my solution called ServiceInterface and ServiceModel. ServiceInterface contains all my services for my application and ServiceModel contains my DTO's and routes etc.. I'm trying to follow the guidelines set out here: Physical Project Structure
My EnquiriesService contains a method to create a new enquiry in my database using a repository:
public void Post(CreateEnquiry request)
{
// Not sure what to do here..
// _repository.Insert(request);
}
My CreateEnquiry request looks like so:
[Api("POST a single Enquiry for Daybook.")]
[Route("/enquiries", "POST")]
public class CreateEnquiry : IReturnVoid { }
As you can see, the CreateEnquiry request object is empty. Do I need to add properties to it to match my Domain Model and then use AutoMapper or something similar to map the fields to my Domain Model and pass that into my repository?
The Insert method on my repository looks like so:
public virtual void Insert(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
DbContext.SaveChanges();
}
Yes. Your Service request, in this case CreateEnquiry needs to have all the properties you need in order to do whatever it is you want to do!
I've seen two different models for Create vs Update:
Use one request objects called, say, SetEnquiry that has a nullable id field. When null and using the POST HTTP verb, it internally creates a new object. And when not null and using the PATCH HTTP verb, it internally updates an object. You can use ServiceStack's implementation of AbstractValidator<T> to add logic such as if POST then id field needs to be null; and if PATCH then id field cannot be null. This will help ensure your data is always as it needs to be.
Create two request objects -- one for Create and one for Update. The Create doesn't even have an id field, and the Update has one and requires it. You can use the same validation technique used above, except applied to each class independently, so you don't need the conditional check of if this verb do this; if that verb do that.
How you map to your data model is up to you. You can use something like AutoMapper or you can use ServiceStack's built-in TranslateTo and PopulateWith methods. I personally take a middle ground: I created my own object extension methods called MapTo and MapFrom that interally call TranslateTo and PopulateWith respectively. Why did I do this? Because then I control those extensions inside my own namespaces and when I need to do special mappings (like a column name doesn't match up, or one object is more complex than the other, or I simply want to ignore a particular column from one of the objects) I simply overload the MapTo and MapFrom with explicit types, giving it higher specificity than the generic methods.
So back to your question specifically. Assuming you're using the built in TranslateTo your service method might look like this:
public void Post(CreateEnquiry request)
{
_repository.Insert(request.TranslateTo<Enquiry>());
}
One more thing: I generally return the object itself when doing a Create and Update. As fields can change (auto-calculated fields, for example) I like to return the object back to the caller. This is preference and has no real bearing on the answer I'm giving you. Just throwing it out there!
I have the following class:
public class FinanceiroLancamento
{
/// <summary>Identificação</summary>
public override int Id { get; set; }
/// <summary>Financeiro caixa</summary>
public FinanceiroLancamentoCaixa FinanceiroLancamentoCaixa { get; set; }
}
public class FinanceiroLancamentoCaixa
{
/// <summary>Identificação</summary>
public override int Id { get; set; }
/// <summary>Identificação do lançamento financeiro</summary>
public int IdFinanceiroLancamento { get; set; }
}
When I try to map and execute migration it´s return:
Property name 'IdFinanceiroLancamento' was already defined.
To solve this problem I needed to comment idfinanceirolancamento and map like this:
HasRequired(e => e.FinanceiroLancamentoCaixa)
.WithRequiredPrincipal()
.Map(m => m.MapKey("IdFinanceiroLancamento"));
The question is:
How can I this FK (FinanceiroLancamento -> FinanceiroLancamentoCaixa) keeping the "IdFinanceiroLancamento { get; set; }"?
This is very important in my case to use later in the class.
Ps: FinanceiroLancamento does not need a FinanceiroLancamentoCaixa, but when FinanceiroLancamentoCaixa exists he needs a FinanceiroLancamento.
Best regards.
Wilton Ruffato Wonrath
Entity Framework requires that 1:1 mappings share the same primary key. In your case, you are trying to use a different member as the mapping id. Also, do not override the base class id, just inherit it.
What you want Is this:
.HasRequired(e => e.FinanceiroLancamentoCaixa)
.WithRequiredPrincipal();
Entity Framework does not allow you to use a 1:1 that is not a shared primary key, so you can't do it in EF. If you absolutely need this, you may have to do it as a stored procedure and call it from EF.
The reason you can't have a 1:1 like this is because the data model allows you to set IdFinanceiroLancamento to the same ID in more than one record, thus breaking your 1:1.
Basically, EF will not allow you to create models with mappings that allow for a violation of the mapping, even if you never create duplicates, it's still a possibility. EF doesn't know about unique constraints either so placing a unique constraint won't tell EF that it's ok.
If you'd like to see this feature, I suggest you vote for it at the EF uservoice:
http://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/1050579-unique-constraint-i-e-candidate-key-support
Let's say I want to create action web site where members would be able to bid for items. To model this domain I have three classes: Member, Item and Bid.
My brainstorming would go something like this:
Item can contain multiple bids
Bid is associated with one Item and one Member
Member can contain multiple bids
Member and Item can exist without bid instance
Bid instance can't exist without both Member and Item
Considering all this it is obvious that since Member and Item objects are independent we can consider them aggregate roots. Bid will be part of one of these aggregate. That is clear but what is confusing to me right now is which aggregate root should I choose? Item or Member?
This is example from Pro ASP.NET MVC 3 Framework book by Apress, and the way they did is like following:
Which gives following code:
public class Member
{
public string LoginName { get; set; } // The unique key
public int ReputationPoints { get; set; }
}
public class Item
{
public int ItemID { get; private set; } // The unique key
public string Title { get; set; }
public string Description { get; set; }
public DateTime AuctionEndDate { get; set; }
public IList<Bid> Bids { get; set; }
}
public class Bid
{
public Member Member { get; set; }
public DateTime DatePlaced { get; set; }
public decimal BidAmount { get; set; }
}
Member and Item are aggregate roots here and Bid is contained within Item.
Now let's say that I have application use case: "Get all bids posted by specific member". Does that mean that I would have to first get all Items (eg. from data base via repository interface) and then enumerate all bids for each Item trying to find matching Member? Isn't that a bit inefficient? So a better way would be then to aggregate Bid objects inside of Member. But in that case consider the new use case: "Get all bids for specific item". Now again we need to go other way around to get all bids...
So taking into account that I need to implement both of these use cases in my application, what is the right and efficient way to model this domain then?
Your domain should really reflect only Command (CQRS) requirements (update/change data). I presume that you need Queries (read data, no update/change of data): "Get all bids for specific item" and "Get all bids posted by specific member". So, this "querying" has nothing to do with the domain, as the query implementation is independent on the command implementation (command is calling a domain method). This gives you a freedom to implement each query in an efficient way. My approach is to implement an efficient DB view getting you only data you want to display in UI. Then you create a new class called BidForItemDto (DTO = data transfer object) and you map data from DB view into a collection of BidForItemDto (you can do it manually via ADO.NET or use NHibernate (preferred, does everything for you)). The same for the second query, create a new class called BidPostedByMemberDto.
So, if it is queries you need, just forget about domain, realize that it's just data you want to display in UI, and query them efficiently from the DB. Only when you do some action in UI (click a button to place a bid for instance), it's executing a command "place a bid", which would at the end call domain method Item.PlaceBid(Member member, DateTime date, decimal amount). And btw, IMHO is it an Item which "has many bids", and the domain method "place bid" would surely need to access previous bids to implement the whole logic correctly. Placing bids collection into Member does not make much sense to me...
From the top of my head some examples of DB views and sql queries:
Get all bids for specific item:
create view BidForItemDto
as
select
i.ItemId,
b.BidId,
b.MemberId,
b.DatePlaced,
b.BidAmount
from Item i
join Bid b ON b.ItemId = i.ItemId
query:
SELECT *
from BidFormItemDto
where ItemId = <provide item id>
Get all bids posted by specific member:
create view BidPostedByMemberDto
as
select
m.MemberId,
b.BidId,
b.MemberId,
b.DatePlaced,
b.BidAmount
from Member m
join Bid b ON b.MemberId = i.MemberId
query:
SELECT *
from BidPostedByMemberDto
where MemberId = <provide member id>