我使用实体框架1与。net 3.5。

我做的事情很简单,就像这样:

var roomDetails = context.Rooms.ToList();

foreach (var room in roomDetails)
{        
   room.LastUpdated = DateTime.Now;
}

当我尝试这样做时,我得到这个错误:

 context.SaveChanges();

我得到了错误:

无法更新EntitySet -因为它有一个DefiningQuery,并且<ModificationFunctionMapping>元素中没有<UpdateFunction>元素来支持当前操作。

我在上下文上做了很多更新,没有任何问题,只有当我试图更新这个特定的实体时。

我所有的搜索结果都是一样的,我要更新的实体上没有声明主键。但是,唉,我有一个主键声明…


当前回答

I found the original answer of updating the .edmx file work best in my situation. I just wasn't too happy about altering the model every time it was updated from the database. That's why I wrote an additional Text Template file, that is automaticaly invoked when after the model has changed - just like the entities are newly generated. I post it here in this comment. To make it work, make sure you name it like {model name}.something.tt, and store it in the same folder as your .edmx folder. I named it {model name}.NonPkTables.tt. It does not generate a file on its own due to the invalid file extension definition in the second line. Feel free to use.

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ output extension="/" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq"#>
<#@ assembly name="%VS120COMNTOOLS%..\IDE\EntityFramework.dll" #>
<#@ assembly name="%VS120COMNTOOLS%..\IDE\Microsoft.Data.Entity.Design.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Windows.Forms" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Data.Entity.Core.Metadata.Edm" #>
<#@ import namespace="System.Data.Entity.Core.Mapping" #>
<#@ import namespace="System.CodeDom" #>
<#@ import namespace="System.CodeDom.Compiler" #>
<#@ import namespace="Microsoft.CSharp"#>
<#@ import namespace="System.Text"#>
<#@ import namespace="System.Diagnostics" #>

<#
    string modelFileName= this.Host.TemplateFile.Split('.')[0] + ".edmx";
    string edmxPath = this.Host.ResolvePath( modelFileName );

    // MessageBox.Show( this.Host.TemplateFile + " applied." );
    var modelDoc = XDocument.Load(edmxPath);
    var root = modelDoc.Root;
    XNamespace nsEdmx = @"http://schemas.microsoft.com/ado/2009/11/edmx";
    XNamespace ns = @"http://schemas.microsoft.com/ado/2009/11/edm/ssdl";

    var runtime = root.Elements(nsEdmx + "Runtime").First();
    var storageModels = runtime.Elements(nsEdmx + "StorageModels").First();
    XNamespace nsStore = @"http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator";

    var schema = storageModels.Elements(ns + "Schema").First();
    XNamespace nsCustomAnnotation = @"http://schemas.microsoft.com/ado/2013/11/edm/customannotation";

    var entityTypes = schema.Nodes().OfType<XComment>().Where(c => c.Value.Contains("warning 6002: The table/view"));
    bool changed = false;

    foreach (var node in entityTypes)
    {
        var element = node.ElementsAfterSelf().First();
        string entityName = element.Attribute("Name").Value;

        // Find EntitySet in EntityContainer.
        var entityContainer = schema.Elements(ns + "EntityContainer").First();
        var entitySet = entityContainer.Elements(ns + "EntitySet").First(s => s.Attribute("Name").Value == entityName);

        // Change "store:Schema" attribute to "Schema" attribute.
        var attribute = entitySet.Attribute(nsStore + "Schema");

        if (attribute != null)
        {
            string schemaName = entitySet.Attribute(nsStore + "Schema").Value;
            entitySet.Attribute(nsStore + "Schema").Remove();
            entitySet.Add(new XAttribute("Schema", schemaName));
            changed |= true;
        }

        // Remove the DefiningQuery element.
        var definingQuery = entitySet.Element(ns + "DefiningQuery");

        if (definingQuery != null)
        {
            definingQuery.Remove();
            changed |= true;        
            Debug.WriteLine(string.Format("Removed defining query of EntitySet {0}.", entityName));
        }
    }

    if (changed)
        modelDoc.Save(edmxPath);
#>

其他回答

我得到了相同的错误消息,但在我的场景中,我试图使用PJT(纯连接表)更新从多对多关系派生的实体。

通过阅读其他帖子,我认为我可以通过在连接表中添加一个额外的PK字段来修复它……但是,如果您将PK列添加到连接表中,那么它就不再是PJT,您将失去实体框架的所有优势,例如实体之间的自动关系映射。

因此,在我的案例中,解决方案是修改DB上的连接表,使PK包含两个外部ID列。

我只需要从模型中删除表,并再次更新模型将表带回来。我猜主键是在将表拉入模型之后创建的。

我遇到了完全相同的问题,不幸的是,添加主键并不能解决问题。下面是我的解决方法:

确保你在表上有一个主键,所以我改变了我的表,添加了一个主键。 删除ADO。NET实体数据模型(edmx文件),我用它来映射和连接我的数据库。 再次添加一个新的ADO文件。NET实体数据模型连接我的数据库和映射我的模型属性。 清理并重新构建解决方案。

问题解决了。

我得到这个问题,因为我正在生成我的EDMX从一个现有的数据库(由别人设计,我使用术语“设计”松散在这里)。

结果发现桌子上根本没有钥匙。EF生成了具有多个键的模型。我必须在SQL中添加一个主键到db表,然后在VS中更新我的模型。

这为我解决了问题。

请注意,也许你的实体有主键,但你的表在数据库中没有主键。